Algoritmos de ordenación

Análisis y Diseño de Algoritmos

Algoritmos de ordenación
Algoritmos básicos: Θ(n2) Ordenación por inserción Ordenación por selección Ordenación por intercambio directo (burbuja) Algoritmos más eficientes Mergesort Quicksort Heapsort Shellsort Algoritmos para casos especiales Binsort (ordenación por urnas) …

1

Introducción
Supongamos un subconjunto de n elementos X = {e1,…,en} de un conjunto referencial Y, X ⊆Y. Dentro de Y se define una relación de orden total ≤ (con las propiedades reflexiva, simétrica y transitiva). El objetivo de la ordenación es encontrar una secuencia de los elementos de X 〈eσ(1),…,eσ(n)〉 tal que se verifique: eσ(1) ≤ … ≤ eσ(n)

2

Introducción
Observaciones Los datos pueden ser simples o complejos. El orden se establece de acuerdo al campo clave. Los conjuntos de datos pueden tener duplicados. Si se mantiene el orden relativo de los datos con clave repetida en el conjunto de datos original, el algoritmo se dice que es estable.
3

ej. Detectar duplicados duplicados. binaria).ej. Ordenar los resultados de una búsqueda en Internet (p. búsqueda binaria). Google PageRank PageRank).ej (p.ej. listado alfabético). . Mostrar un listado ordenado del contenido de una base de datos (p. Encontrar la mediana. .ej. Problemas que resultan más sencillos de resolver con los datos ordenados ordenados: : Realizar una búsqueda (p.ej. alfabético). 5 . . directorio. . 4 Aplicaciones Aplicaciones evidentes: evidentes: Mostrar los ficheros de un directorio. p. Encontrar el par más cercano cercano.Introducción Tipos de algoritmos de ordenación Algoritmos de ordenación interna: En memoria principal (acceso aleatorio) Algoritmos de ordenación externa: En memoria secundaria (restricciones de acceso). Identificar “outliers” / anomalías anomalías. ). mediana. p.

tareas. Simulación (p.Aplicaciones Otras aplicaciones (puede que no tan evidentes) evidentes) : Compresión de datos. datos. Planificación de tareas. p. Árbol generador minimal [MST: Minimum Spanning Tree] Gestión de la cadena de suministro [SCM: Supply Chain Management] Recomendaciones de libros en Amazon.ej. paralelo. . Informática gráfica gráfica. Balanceado de carga en un ordenador paralelo. . sistemas de partículas).com … 6 Ordenación por selección En cada iteración.ej. partículas). Biología computacional computacional. se selecciona el menor elemento del subvector no ordenado y se intercambia con el primer elemento de este subvector subvector: : 7 .

// Coloca el mínimo en v[i] tmp = v[ v[i i].length.. i++) { // Menor elemento del vector v[i.length v. j++) if (v[j]<v[pos_min (v[j]<v[pos_min]) ]) pos_min = j. .N-1] pos_min = i. i<N<N-1. v[pos_min v[pos_min] ] = tmp tmp. . . . // Coloca el mínimo en v[i] tmp = v[ v[i i]. ]. i<N<N-1. int N = v. j. i++) { // Menor elemento del vector v[i.. v[i v[i] = v[ v[pos_min pos_min].N-1] pos_min = i.. .Nv[i. j<N. pos_min pos_min. int N = v. int i. . for (j=i+1. j. = } } 9 .length. j++) if (v[j]<v[pos_min (v[j]<v[pos_min]) ]) pos_min = j.. j<N.Nv[i. v[i v[i] = v[ v[pos_min pos_min]. int i. for (i (i=0. . for (j=i+1. pos_min pos_min. ]. v[pos_min v[pos_min] ] = tmp tmp.Ordenación por selección void selectionSort (double v[]) { double tmp tmp. for (i (i=0. . = } } 8 Ordenación por selección void selectionSort (double v[]) { double tmp tmp.length v.

10 Ordenación por inserción En cada iteración. se inserta un elemento del subvector no ordenado en la posición correcta dentro del subvector ordenado.Ordenación por inserción En cada iteración. 11 . se inserta un elemento del subvector no ordenado en la posición correcta dentro del subvector ordenado.

i<N. for (i (i=1. . v[j] = tmp tmp. . (j>0) && ( (tmp tmp<v[j <v[j-1]). int N = v. i++) { tmp = v[ v[i i].length. j. .Ordenación por inserción void insertionSort (double v[]) { double tmp tmp. j j---) ) v[j] = v[jv[j-1].length v. int i. for (j= (j=i i. } } 12 Método de la burbuja Ordenación por intercambio directo IDEA: Los elementos más ligeros ascienden 13 .

j.length . int N = v. v[jv[j -1] = tmp tmp.j i. . i++) for (j = N – 1. for (i = 0. double tmp tmp. . v[i] = v[i + 1]. . j = 0.Método de la burbuja void bubbleSort (double v[]) { double tmp tmp. .length. i < v. . j j---) ) if (v[j] < v[jv[j-1]) { tmp = v v[j]. i < N – 1. } } } 15 . } } 14 Método de la burbuja Mejora: Usar un centinela y terminar cuando en una iteración del bucle interno no se produzcan intercambios. for (i = 0. v[j] = v[jv[j-1]. swapped = true. . j > i. while (swapped swapped) ) { swapped = false. v[i + 1] = tmp tmp.length v.j. void bubbleSort bubbleSort( (double double[] [] v) { boolean swapped = true. int i. j++ . j++. [j]. int i. i++) if (v[i] > v[i + 1]) { tmp = v[i].

Combinar las dos mitades ordenadas: O(n). Dividir nuestro conjunto en dos mitades. 16 Mergesort Algoritmo de ordenación “divide y vencerás”: 1. Ordenar recursivamente cada mitad. 17 . Casi lineal para conjuntos casi ordenados. Lineal en su versión mejorada si el vector está ordenado. Ordenación por inserción N2/4 comparaciones y N2/8 intercambios en media El doble en el peor caso. 3.Análisis de eficiencia Ordenación por selección N2/2 comparaciones y N intercambios. 2. Ordenación por burbuja N2/2 comparaciones y N2/2 intercambios en media (y en el peor caso).

A A G L O R H I M S T Optimización: “In“In-place merge” merge” ( (Kronrud Kronrud. 19 . . Repetir hasta que se hayan añadido todos los elementos. 1969) Cantidad constante de almacenamiento extra. Añadir el más pequeño de los dos a un vector auxiliar.Mergesort A A A A L G L G L G G O O H O R R I R I I H T T I O H H M R M M S S S S T T Dividir O(1) Ordenar 2T(n/2) Mezclar O(n) L M 18 Mergesort ¿Cómo combinar eficientemente dos listas ordenadas? Usando un array auxiliar y un número lineal de comparaciones: Controlar la posición del elemento más pequeño en cada mitad.

Mergesort A A G L O R H I M S T A A G G L O R H I M S T 20 Mergesort A A G G L H O R H I M S T A A G G L H O I R H I M S T 21 .

Mergesort A A G G L H O I R L H I M S T A A G G L H O I R L M H I M S T 22 Mergesort A A G G L H O I R L M H O I M S T A A G G L H O I R L M H O I R M S T 23 .

A A G L O R H I M S T Optimización: “In“In-place merge” merge” ( (Kronrud Kronrud. 1969) Cantidad constante de almacenamiento extra. Añadir el más pequeño de los dos a un vector auxiliar. . 25 .Mergesort A A G G L H O I R L M H O I R M S S T A A G G L H O I R L M H O I R M S S T T 24 Mergesort ¿Cómo combinar dos listas ordenadas eficientemente? Usando un array auxiliar y un número lineal de comparaciones: Controlar la posición del elemento más pequeño en cada mitad. Repetir hasta que se hayan añadido todos los elementos.

.. n > 1 T(n) n 2(n/2) T(n/2) T(n/2) T(n/4) T(n/4) T(n/4) T(n/4) log2n 4(n/4) .Mergesort 26 Mergesort: Mergesort : Eficiencia 1. T(n / 2k) .. n =1  T ( n) = 2T ( n / 2) + n. T(2) T(2) T(2) T(2) T(2) T(2) T(2) T(2) n/2 (2) 27 n log2n ..

n > 1 Usando el método de la ecuación característica: ti = T (2i ) ti = 2ti −1 + 2i ⇒ ti = c1 2i + c2i 2i T (n) = c1 2 log 2 ( n ) + c2 log 2 (n)2log 2 ( n ) = c1n + c2 n log 2 (n) T (n) es O(n log 2 n) 29 . n > 1 Expandiendo la recurrencia: T ( n) n = = = L = = T ( n / n) n/n log 2 n +1+L+1 1 2 3 log 2 n 2T (n / 2) n T ( n / 2) n/2 T ( n / 4) n/4 +1 +1 +1+1 28 Mergesort: Mergesort : Eficiencia 1. n =1  T ( n) = 2T ( n / 2) + n.Mergesort: Mergesort : Eficiencia 1. n =1  T ( n) = 2T ( n / 2) + n.

length-1). dcha dcha). pivote+1. izda izda. int izda izda. 30 Quicksort void quicksort (double v[]. Se toma un elemento arbitrario del vector. // Posición del pivote if (izda izda< <dcha dcha) ) { pivote = partir (v. al que denominaremos pivote (p). quicksort (v. } } Uso: quicksort (vector. vector. int dcha dcha) ) { int pivote. . quicksort (v. pivote pivote-1). mientras que los que quedan a la derecha son mayores que él. ). Ordenamos. . izda izda.length vector. 0. 3. las dos zonas delimitadas por el pivote. 31 . dcha dcha). .Quicksort 1. ). Se divide el vector de tal forma que todos los elementos a la izquierda del pivote sean menores que él. por separado. 2.

Quicksort Obtención del pivote Mientras queden elementos mal colocados con respecto al pivote: Se recorre el vector. Se intercambian los elementos situados en las casillas i y j (de modo que. hasta encontrar otro elemento situado en una posición j tal que v[j] < p. de izquierda a derecha. 32 Quicksort 33 . ahora. hasta encontrar un elemento situado en una posición i tal que v[i] > p. de derecha a izquierda. Se recorre el vector. v[i] < p < v[j]).

izda++. int ultimo) { // Valor del pivote double pivote = v[primero]. 34 Quicksort: Quicksort : Eficiencia En el peor caso T(n) = T(1) + T(nT(n-1) + c·n ∈ O(n2) Tamaño de los casos equilibrado (idealmente. . while ((izda ((izda<= <=dcha dcha) ) && (v[dcha (v[dcha]>pivote)) ]>pivote)) dcha-dcha --. izda ++. } while (( ((izda izda<= <=dcha dcha) ) && (v[izda (v[izda]<= ]<=pivote pivote)) )) izda++. . dcha-dcha --. // Variable auxiliar double temporal. // Colocar el pivote en su sitio temporal = v[primero]. ). ]. int dcha = ultimo. // Posición del pivote return dcha dcha. v[izda v[izda] ] = v[ v[dcha dcha]. do { // Pivotear Pivotear… … if (izda < dcha dcha) ) { temporal = v[izda v[izda]. izda ++.Quicksort int partir (double v[]. ]. v[primero] = v[dcha v[dcha]. v[dcha v[dcha] ] = temporal. ]. int izda = primero+1. v[dcha v[dcha] ] = temporal. usando la mediana como pivote) T(n) = 2T(n/2) + c·n ∈ O(n log n) Promedio 1 n −1 2 n −1 T (n) = ∑ [T (n − i ) + T (i )] + cn = ∑ T (i ) + cn ∈ O( n log n) n i =1 n i =1 35 . . int primero primero. } } while (izda <= dcha dcha). .

Heapsort O(n log n) 36 Heapsort: Heapsort : Eficiencia 1. n). Por tanto.Heapsort Algoritmo de ordenación de la familia del algoritmo de ordenación por selección basado en la construcción de un árbol parcialmente ordenado (“heap (“heap”). el heapsort es O(n log n). Construcción inicial del heap: heap: n operaciones de inserción O(log n) sobre un árbol parcialmente ordenado ⇒ O(n log n). n). ”). 2. 37 . Extracción del menor/mayor elemento del heap: heap: n operaciones de borrado O(log n) sobre un árbol parcialmente ordenado ⇒ O(n log n).

1959). Inserción O(n2) Shellsort O(nlog2 n) 39 . ordena el vector (Donald Shell. ordena el vector (Donald Shell. 1959).Shellsort Mejora del algoritmo de ordenación por inserción: Compara elementos separados por varias posiciones y. en varias pasadas de saltos cada vez menores. 38 Shellsort Mejora del algoritmo de ordenación por inserción: Compara elementos separados por varias posiciones y. en varias pasadas de saltos cada vez menores.

v[v[i]] = v[i]. i < v. . i++) while (v[i] != i) { int tmp = v[v[i]]. .length.Bucket sort & Binsort Se divide el array en un conjunto de “urnas” y cada urna se ordena por separado: O(n2) Bajo ciertas condiciones (claves entre 0 y NN-1 sin duplicados). } } 40 Otros algoritmos Radix sort Histogram sort Counting sort = ultra sort = math sort Tally sort Pigeonhole sort Bead sort Timsort Smoothsort … 41 . v[i] = tmp tmp.length v. la ordenación se puede hacer en O(n): void binSort (int int[] [] v) { for (int i = 0.

Resumen Burbuja Selección 42 Resumen Inserción Shellsort 43 .

Resumen Heapsort Quicksort 44 Resumen Timsort: Timsort : Mergesort + Ordenación por inserción 45 .