0% encontró este documento útil (0 votos)
6 vistas56 páginas

Tema 3 - Ordenación

Cargado por

pau.frangi
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
6 vistas56 páginas

Tema 3 - Ordenación

Cargado por

pau.frangi
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 56

Algoritmos de ordenación

y gestión de datos ordenados


Alberto Verdejo
Facultad de Informática (UCM)

Fundamentos de la programación II
Problema

‣ Dada una colección de datos que se pueden comparar con una relación de
orden, <, producir una secuencia de esos datos de tal forma que ninguno sea
menor que los que le preceden.

‣ Hay literalmente docenas de algoritmos de ordenación.


‣ Nosotros vamos a estudiar algunos de ellos y en próximos cursos estudiaréis
otros.
Ordenación por inserción
‣ Se recorren los elementos de izquierda a derecha y cada elemento se coloca
en el lugar que le toca entre los anteriores que previamente ya han sido
ordenados.

para i = 1 hasta N – 1:
// V[0..i) está ordenado
j=i
mientras j > 0 && V[ j ] < V[ j – 1]:
intercambiar V[ j ] con V[ j – 1]
j=j–1
// V[0..N) está ordenado
Ordenación por inserción. Ejemplo
Ordenación por inserción: implementación
‣ Ordenación de un vector de enteros:
void ordenar_insercion(vector<int> &/*ent/sal*/ array) {
size_t N = array.size();
// parte ordenada array[0..i), parte por procesar array[i..N)
for (size_t i = 1; i < N; ++i) { // desde el segundo hasta el último
int elemento = array[i]; // elemento a insertar
size_t j = i; // desplazar los mayores de la parte ordenada
while (j > 0 && elemento < array[j - 1]) {
array[j] = array[j - 1];
--j;
}
array[j] = elemento; // colocar en el hueco
}
// parte ordenada array[0..N)
}
Ordenación por inserción: implementación
‣ ¿Y si queremos ordenar strings?
void ordenar_insercion(vector<string> &/*ent/sal*/ array) {
size_t N = array.size();
// parte ordenada array[0..i), parte por procesar array[i..N)
for (size_t i = 1; i < N; ++i) { // desde el segundo hasta el último
string elemento = array[i]; // elemento a insertar
size_t j = i; // desplazar los mayores de la parte ordenada
while (j > 0 && elemento < array[j - 1]) {
array[j] = array[j - 1];
--j;
}
array[j] = elemento; // colocar en el hueco
}
// parte ordenada array[0..N)
}
Ordenación por inserción: implementación
‣ ¡Los templates nos salvan!
template <typename T>
void ordenar_insercion(vector<T> &/*ent/sal*/ array) {
size_t N = array.size();
// parte ordenada array[0..i), parte por procesar array[i..N)
for (size_t i = 1; i < N; ++i) { // desde el segundo hasta el último
T elemento = array[i]; // elemento a insertar
size_t j = i; // desplazar los mayores de la parte ordenada
while (j > 0 && elemento < array[j - 1]) {
array[j] = array[j - 1];
--j;
}
array[j] = elemento; // colocar en el hueco
}
// parte ordenada array[0..N)
}
Ordenación por inserción: implementación
‣ ¿Y si queremos ordenar de mayor a menor?
template <typename T>
void ordenar_insercion(vector<T> &/*ent/sal*/ array) {
size_t N = array.size();
// parte ordenada array[0..i), parte por procesar array[i..N)
for (size_t i = 1; i < N; ++i) { // desde el segundo hasta el último
T elemento = array[i]; // elemento a insertar
size_t j = i; // desplazar los mayores de la parte ordenada
while (j > 0 && elemento > array[j - 1]) {
array[j] = array[j - 1];
--j;
}
array[j] = elemento; // colocar en el hueco
}
// parte ordenada array[0..N)
}
Ordenación por inserción: implementación
‣ ¡Los templates nos salvan de nuevo! #include <functional>

template <typename T, class Comp = less<T>>


void ordenar_insercion(vector<T> &/*ent/sal*/ array, Comp ord = Comp()) {
size_t N = array.size();
// parte ordenada array[0..i), parte por procesar array[i..N)
for (size_t i = 1; i < N; ++i) { // desde el segundo hasta el último
T elemento = array[i]; // elemento a insertar
size_t j = i; // desplazar los mayores de la parte ordenada
while (j > 0 && ord(elemento, array[j - 1])) {
array[j] = array[j - 1];
--j;
}
array[j] = elemento; // colocar en el hueco
}
// parte ordenada array[0..N)
}
Ordenación por inserción: ejemplo

vector<int> enteros;

enteros 20 7 14 32 5 14 17 12 13 15

ordenar_insercion(enteros);

enteros 5 7 12 13 14 14 15 17 20 32

ordenar_insercion(enteros, greater<int>());

enteros 32 20 17 15 14 14 13 12 7 5
Ordenación por inserción: ejemplo

vector<string> datos;

datos Zorro leon abeja Lobo perro gato

ordenar_insercion(datos);

datos Lobo Zorro abeja gato leon perro


Definición de un comparador
‣ Podemos definir nuestro propio comparador:
class ComparaSinMayus {
public:
bool operator()(string const& a, string const& b) {
size_t i = 0;
while (i != a.length()) {
if (i == b.length() || tolower(b[i]) < tolower(a[i]))
return false;
else if (tolower(a[i]) < tolower(b[i])) return true;
++i;
}
return i != b.length();
}
};
Definición de un comparador

vector<string> datos;

datos Zorro leon abeja Lobo perro gato

ordenar_insercion(datos, ComparaSinMayus());

datos abeja gato leon Lobo perro Zorro


Ordenación por inserción, más modular

template <typename T, class Comp = less<T>>


void ordenar_insercion(vector<T> &/*ent/sal*/ array, Comp ord = Comp()) {
size_t N = array.size();
// parte ordenada array[0..i), parte por procesar array[i..N)
for (size_t i = 1; i < N; ++i) { // desde el segundo hasta el último
insertar_ordenado(array, i, ord);
}
// parte ordenada array[0..N)
}
Insertar de forma ordenada (auxiliar)
template <typename T, class Comp = less<T>>
void insertar_ordenado(vector<T> &/*ent/sal*/ array, size_t i, Comp ord = Comp()) {
// parte ordenada array[0..i)
T elemento = array[i]; // elemento a insertar
size_t j = i; // desplazar los mayores de la parte ordenada
while (j > 0 && ord(elemento, array[j - 1])) {
array[j] = array[j - 1];
--j;
}
array[j] = elemento; // colocar en el hueco
}
Insertar de forma ordenada

template <typename T, class Comp = less<T>>


void insertar_ordenado(vector<T> &/*ent/sal*/ array, T const& elemento,
Comp ord = Comp()) {
// array[0..N) ordenado
array.push_back({}); // hacer hueco al nuevo elemento
size_t j = array.size() - 1; // desplazar los mayores de la parte ordenada
while (j > 0 && ord(elemento, array[j - 1])) {
array[j] = array[j - 1];
--j;
}
array[j] = elemento; // colocar en el hueco
// array[0..N+1) ordenado y con el valor elemento insertado en su lugar
}
Insertar de forma ordenada: ejemplo

datos abeja gato leon Lobo perro Zorro

insertar_ordenado(datos, string("buho"));

datos abeja gato leon Lobo perro Zorro buho

insertar_ordenado(datos, string("buho"), ComparaSinMayus());

abeja buho gato leon Lobo perro Zorro


Ordenación por selección
‣ Se selecciona cada vez el menor elemento de la parte no ordenada y se
coloca al principio de esa parte, detrás de los ya ordenados (que son todos
menores).

para i = 0 hasta N – 2:
// V[0..i) está ordenado
jMin = i
para j = i + 1 hasta N – 1:
si V[ j ] < V[ jMin ]:
jMin = j
intercambiar V[ i ] con V[ jMin ]
// V[0..N) está ordenado
Ordenación por selección. Ejemplo
Ordenación por selección: implementación

template <typename T, typename Comp = less<T>>


void ordenar_seleccion(vector<T> &/*ent/sal*/ array, Comp ord = Comp()) {
size_t N = array.size();
// ordenado array[0..i) y todos los elementos de la parte ordenada
// son "menores" (o iguales) que los de la parte no ordenada
for (size_t i = 0; i + 1 < N; ++i) { // hasta el penúltimo
// colocar el "menor" de la parte no ordenada (array[i..N)) en array[i]
size_t menor = i;
for (size_t j = i + 1; j < N; ++j)
if (ord(array[j], array[menor])) menor = j;
swap(array[i], array[menor]);
}
// parte ordenada array[0..N)
}
Ordenación por el método de la burbuja
‣ Compara pares de elementos consecutivos y si no están bien ordenados, los
intercambia. En cada pasada, el mayor de la parte no ordenada termina al
final de esa parte (y delante de los ya ordenados).

para i = 1 hasta N – 1:
// V[N – i + 1..N) está ordenado
para j = 0 hasta N – i:
si V[ j + 1 ] < V[ j ]:
intercambiar V[ j ] con V[ j + 1 ]
// V[0..N) está ordenado
Ordenación por el método de la burbuja. Ejemplo
Ordenación por el método de la burbuja: implementación
template <typename T, typename Comp = less<T>>
void ordenar_burbuja(vector<T> &/*ent/sal*/ array, Comp ord = Comp()) {
size_t N = array.size();
bool inter = true;
size_t i = 1;
// ordenado array[N-i+1..N) y todos los elementos de la parte
// ordenada son "mayores" (o iguales) que los de la parte no ordenada
while (i < N && inter) { // hasta el penúltimo
// colocar el mayor de la parte no ordenada en array[N-i]
// intercambiando, desde el primero, con los elementos menores
inter = false; // y comprobando si se realiza algún intercambio
for (size_t j = 0; j < N-i; ++j)
if (ord(array[j+1], array[j])) {
swap(array[j], array[j+1]);
inter = true;
}
++i;
}
}
// parte ordenada array[0..N)
Inserción vs Burbuja
std::sort en la librería algorithm de la STL

‣ Ordena utilizando una combinación de algoritmos de ordenación muy


eficientes (se estudian en segundo y tercero).
vector<int> datos = { 12, 4, 28, 7, 20, 12, 1, 140 };

sort(datos.begin(), datos.end());

1 4 7 12 12 20 28 140

sort(datos.begin(), datos.end(), greater<int>());

140 28 20 12 12 7 4 1
Comprobar si un vector está ordenado

template <typename T, typename Comp = less<T>>


bool ordenado(vector<T> const& array, Comp ord = Comp()) {
bool ordenado = true;
for (size_t i = 1; i < array.size() && ordenado; ++i) {
ordenado = !ord(array[i], array[i - 1]); // se admiten repeticiones
}
return ordenado;
}
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 13

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 13

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 13

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 13

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 13

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 10

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 10

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 10

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado
‣ Buscamos un elemento en un vector. Queremos saber si está o no, y en caso
de que esté, dónde.
‣ No hace falta buscar en todo el vector. Si buscamos de izquierda a derecha
podemos parar en cuanto encontremos un elemento que no sea menor que el
buscado.

Buscamos el 10

enteros 5 7 12 13 14 14 15 17 20 32
Búsqueda secuencial en un vector ordenado: implementación

template <typename T, typename Comp = less<T>>


bool busqueda_secuencial(vector<T> const& array, T const& buscado,
size_t &/*sal*/ pos, Comp ord = Comp()) {
size_t N = array.size();
pos = 0;
// array[0..pos) < buscado
while (pos < N && ord(array[pos], buscado))
++pos;
// buscado <= array[pos..N)
return pos < N && !ord(buscado, array[pos]);
// encontrado, buscado == array[pos]
// no encontrado, puede insertarse en la posición pos
}
Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 10
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz m dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 10
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz m dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 10
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz m dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 10
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 20
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz m dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 20
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz m dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 20
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz m dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria
‣ Si buscamos en un vector ordenado, podemos con cada comparación
categorizar como menores que el elemento buscado x, o como mayores o
iguales, a la mitad de los elementos aún sin categorizar.
‣ Para ello cada vez comparamos x con el elemento en la posición de en medio.
Buscamos el 20
0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 14 14 15 17 20 32

iz dr

enteros[0..iz] < x y x ⩽ enteros[dr..N)


Búsqueda binaria: implementación

template <typename T, typename Comp = less<T>>


bool busqueda_binaria(vector<T> const& array, T const& buscado,
size_t &/*sal*/ pos, Comp ord = Comp()) {
int iz = -1, dr = array.size();
// 0 <= iz < dr <= N
// array[0..iz] < buscado Y buscado <= array[dr..N)
while (iz + 1 < dr) { // hay elementos sin categorizar
int mitad = (iz + dr) / 2;
if (ord(array[mitad], buscado)) iz = mitad;
else dr = mitad;
}
pos = dr;
return pos < array.size() && !ord(buscado, array[pos]);
}
Operaciones con listas ordenadas: Inserción
‣ Insertar sin repeticiones.
Insertar el 16

0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 20 23 30 35 40 48
Operaciones con listas ordenadas: Inserción
‣ Insertar sin repeticiones.
Insertar el 16

0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 20 23 30 35 40 48
Operaciones con listas ordenadas: Inserción
‣ Insertar sin repeticiones.
Insertar el 16

0 1 2 3 4 5 6 7 8 9 10

enteros 5 7 12 13 20 23 30 35 40 48
Operaciones con listas ordenadas: Inserción
‣ Insertar sin repeticiones.
Insertar el 16

0 1 2 3 4 5 6 7 8 9 10

enteros 5 7 12 13 20 23 30 35 40 48
Operaciones con listas ordenadas: Inserción
‣ Insertar sin repeticiones.
Insertar el 16

0 1 2 3 4 5 6 7 8 9 10

enteros 5 7 12 13 16 20 23 30 35 40 48
Operaciones con listas ordenadas: Inserción
template <typename T>
void desplazar_derecha(vector<T> &/*ent/sal*/ array, size_t pos) {
array.push_back({}); // crear un nuevo hueco
for (size_t i = array.size() - 1; i > pos; --i)
array[i] = array[i - 1];
}

template <typename T, typename Comp = less<T>>


bool insertar(vector<T> &/*ent/sal* array, T const& dato, Comp ord = Comp()) {
size_t pos = 0;
if (!busqueda_binaria(array, dato, pos, ord)) {
desplazar_derecha(array, pos);
array[pos] = dato;
return true;
}
else return false;
}
Operaciones con listas ordenadas: Eliminación
‣ Eliminar un elemento, si existe.
Eliminar el 23

0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 20 23 30 35 40 48
Operaciones con listas ordenadas: Eliminación
‣ Eliminar un elemento, si existe.
Eliminar el 23

0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 20 23 30 35 40 48
Operaciones con listas ordenadas: Eliminación
‣ Eliminar un elemento, si existe.
Eliminar el 23

0 1 2 3 4 5 6 7 8 9

enteros 5 7 12 13 20 30 35 40 48
Operaciones con listas ordenadas: Eliminación
‣ Eliminar un elemento, si existe.
Eliminar el 23

0 1 2 3 4 5 6 7 8

enteros 5 7 12 13 20 30 35 40 48
Operaciones con listas ordenadas: Eliminación
template <typename T>
void desplazar_izquierda(vector<T> &/*ent/sal*/ array, size_t pos) {
for (size_t i = pos + 1; i < array.size(); ++i)
array[i - 1] = array[i];
array.pop_back();
}

template <typename T, typename Comp = less<T>>


bool eliminar(vector<T> &/*ent/sal*/ array, T const& dato, Comp ord = Comp()) {
size_t pos = 0;
if (busqueda_binaria(array, dato, pos, ord)) {
desplazar_izquierda(array, pos);
return true;
}
else return false;
}

También podría gustarte