Algoritmos de ordenación Análisis y Diseño de Algoritmos
Algoritmos de ordenación
Algoritmos básicos: ΘΘ(n(n 22)) 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) 11 …… Introducción
Supongamos un subconjunto de n elementos
X = {e 11,…,e nn} 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 〈〈eeσσ(1)(1) ,…,e σσ(n)(n) 〉〉 tal que se verifique: e σσ(1)(1) ≤ … ≤≤eeσσ(n)(n)
22
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 .. 33 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).
44
Aplicaciones
Aplicaciones evidentes:: evidentes Mostrar los ficheros de un directorio..directorio Mostrar un listadoordenado del contenidode unabase de datos ((p.ejp.ej.. listadoalfabético).). alfabético Ordenar los resultados de unabúsqueda en Internet (p.ej( p.ej.. Google PageRank ).). Problemas que resultan más sencillos de resolver con los datos ordenadosordenados:: Realizar una búsqueda ((p.ejp.ej.. búsquedabinaria).). binaria Encontrar la mediana.mediana . Encontrar el par más cercanocercano.. Identificar “outliers” / anomalíasanomalías.. Detectar duplicadosduplicados.. 55 Aplicaciones
Otras aplicaciones ((puedepuedeque no tan evidentes)evidentes :) : Compresión de datos..datos Informática gráficagráfica.. Planificación de tareas..tareas Balanceado de carga en un ordenadorparalelo.. paralelo Biología computacional .. Simulación ((p.ejp.ej.. sistemas de partículas).).partículas Árbol generador minimal [MST: Minimum Spanning Tree] Gestión de la cadenade suministro [SCM: Supply Chain Management] Recomendaciones de librosen Amazon.com ……
66
Ordenación por selección
En cada iteración, se selecciona el menor elemento del subvector no ordenado y se intercambia con el primer elemento de este subvectorsubvector::
77 Ordenación por selección void selectionSort (double v[]) {{ double tmptmp;; int ii,, j, pos_minpos_min;; int N = v.lengthv.length;;
for ((ii=0;=0; ii // Menor elemento del vector v[i..N --1]1] pos_min = ii;; for (j=i+1; j // Coloca el mínimo en v[i] tmp = v[v[ii];]; v[v[ii]] = v[v[pos_minpos_min];]; v[v[pos_minpos_min]] = tmptmp;; }} }} 88 Ordenación por selección void selectionSort (double v[]) {{ double tmptmp;; int ii,, j, pos_minpos_min;; int N = v.lengthv.length;; for ((ii=0;=0; ii // Menor elemento del vector v[i..N --1]1] pos_min = ii;; for (j=i+1; j // Coloca el mínimo en v[i] tmp = v[v[ii];]; v[v[ii]] = v[v[pos_minpos_min];]; v[v[pos_minpos_min]] = tmptmp;; }} }} 99 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. 1010 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. 1111 Ordenación por inserción void insertionSort (double v[]) {{ double tmptmp;; int ii,, j; int N = v.lengthv.length;; for ((ii=1;=1; ii tmp = v[v[ii];]; for (j=(j=ii;; (j>0) && ((tmptmp v[j] = tmptmp;; }} }} 1212 Método de la burbuja Ordenación por intercambio directo IDEA: Los elementos más ligeros ascienden 1313 Método de la burbuja void bubbleSort (double v[]) {{ double tmptmp;; int i,ji,j;; int N = v.lengthv.length;; for (i = 0; i < N ––1;1; i++) for (j = N ––1;1; j > i; jj----)) ifif (v[j] < v[j --1]) { tmp = vv[j];[j]; v[j] = v[jv[j--1];1]; v[jv[j--1]1] = tmptmp;; }} }} 1414 Método de la burbuja Mejora: Usar un centinela y terminar cuando en una iteración del bucle interno no se produzcan intercambios. void bubbleSortbubbleSort((doubledouble[][] v) {{ boolean swapped ==true;true; int i, j = 0; double tmptmp;; while ((swappedswapped)) { swapped ==false;false; j++j++;; for (i = 0; i < v.length --j;j; i++) ifif (v[i] > v[i + 1]) { tmp = v[i]; v[i] = v[i + 1]; v[i + 1] = tmptmp;; swapped ==true;true; }} }} 1515 }} Análisis de eficiencia Ordenación por selección NN22/2 comparaciones y N intercambios. Ordenación por inserción NN22/4 comparaciones y N 22/8 intercambios en media El doble en el peor caso. Casi lineal para conjuntos casi ordenados. Ordenación por burbuja NN22/2 comparaciones y N 22/2 intercambios en media (y en el peor caso). Lineal en su versión mejorada si el vector está ordenado. 1616 Mergesort Algoritmo de ordenación “divide y vencerás”: 1.1. Dividir nuestro conjunto en dos mitades. 2.2. Ordenar recursivamente cada mitad. 3.3. Combinar las dos mitades ordenadas: O(n). 1717 Mergesort A L G O R I T H M S A L G O R I T H M S Dividir O(1) A G L O R H I M S T Ordenar 2T(n/2) A G H I L M O R S T Mezclar O(n) 1818 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. Añadir el más pequeño de los dos a un vector auxiliar. Repetir hasta que se hayan añadido todos los elementos. A G L O R H I M S T A Optimización: “In“In placeplace merge”merge (” (KronrudKronrud,, 1969) 1919 Cantidad constante de almacenamiento extra. Mergesort A G L O R H I M S T A A G L O R H I M S T A G 2020 Mergesort A G L O R H I M S T A G H A G L O R H I M S T A G H I 2121 Mergesort A G L O R H I M S T A G H I L A G L O R H I M S T A G H I L M 2222 Mergesort A G L O R H I M S T A G H I L M O A G L O R H I M S T A G H I L M O R 2323 Mergesort A G L O R H I M S T A G H I L M O R S A G L O R H I M S T A G H I L M O R S T 2424 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. Añadir el más pequeño de los dos a un vector auxiliar. Repetir hasta que se hayan añadido todos los elementos. A G L O R H I M S T A Optimización: “In“In placeplace merge”merge (” (KronrudKronrud,, 1969) 2525 Cantidad constante de almacenamiento extra. Mergesort 2626 MergesortMergesort:: Eficiencia ,1 n =1 T(n) = 2T(n )2/ + n, n >1 T(n) n T(n/2) T(n/2) 2(n/2) T(n/4) T(n/4) T(n/4) T(n/4) 4(n/4) log 2n . . . T(n / 2 k) . . . T(2) T(2) T(2) T(2) T(2) T(2) T(2) T(2) n/2 (2) 2727 n log 2n MergesortMergesort:: Eficiencia ,1 n =1 T(n) = 2T(n )2/ + n, n >1 Expandiendo la recurrencia: T (n) 2T (n )2/ = +1 n n T (n )2/ = +1 n 2/ T (n )4/ = +1+1 n 4/ L T (n / n) = +1+L+1 n n 123 / n log2 n 2828 = log2 MergesortMergesort:: Eficiencia ,1 n =1 T(n) = 2T(n )2/ + n, n >1 Usando el método de la ecuación característica: i t t i t c i c i i ti =T 2( ) i = 2 i−1 + 2 ⇒ i = 1 2 + 2 2 n n T n c log2 ( ) c n log2 ( ) c n c n n ( ) = 1 2 + 2 log2 ( 2) = 1 + 2 log2 ( ) T n n n 2929 ( ) es O ( log2 ) Quicksort 1.1. Se toma un elemento arbitrario del vector, al que denominaremos pivote (p). 2.2. Se divide el vector de tal forma que todos los elementos a la izquierda del pivote sean menores que él, mientras que los que quedan a la derecha son mayores que él. 3.3. Ordenamos, por separado, las dos zonas delimitadas por el pivote. 3030 Quicksort void quicksort (double v[], int izdaizda,, int dchadcha)) {{ int pivote; // Posición del pivote ifif ((izdaizda< pivote = partir (v, izda , dcha );); quicksort (v, izdaizda,, pivotepivote--1);1); quicksort (v, pivote+1, dchadcha);); }} }} Uso: quicksort (vector, 0, vector.lengthvector.length--1);1); 3131 Quicksort Obtención del pivote Mientras queden elementos mal colocados con respecto al pivote: Se recorre el vector, de izquierda a derecha, hasta encontrar un elemento situado en una posición i tal que v[i] > p. Se recorre el vector, de derecha a izquierda, hasta encontrar otro elemento situado en una posición j tal que v[j] < p. Se intercambian los elementos situados en las casillas i y j (de modo que, ahora, v[i] < p < v[j]). 3232 Quicksort 3333 Quicksort int partir (double v[], int primeroprimero,, int ultimo) {{ ifif ((izdaizda< dchadcha)) { // Valor del pivote temporal = v[v[izdaizda];]; double pivote = v[primero]; v[v[izdaizda]] = v[v[dchadcha];]; v[v[dchadcha]] = temporal; // Variable auxiliar dchadcha----;; double temporal; izda ++; }} int izda = primero+1; int dcha = ultimo; } while ((izdaizda <= dchadcha);); do { // PivotearPivotear…… // Colocar el pivote en su sitio temporal = v[primero]; while ((((izdaizda<=<=dchadcha)) v[primero] = v[v[dchadcha];]; && (v[(v[izdaizda]<=]<=pivotepivote)))) v[v[dchadcha]] = temporal; izdaizda++;++; while ((((izdaizda<=<=dchadcha)) // Posición del pivote && (v[(v[dchadcha]>pivote))]>pivote)) return dchadcha;; dchadcha----;; }} 3434 QuicksortQuicksort:: Eficiencia En el peor caso T(n) = T(1) + T(nT(n 1)1) + c·nc·n ∈∈ O(n 22)) Tamaño de los casos equilibrado (idealmente, usando la mediana como pivote) T(n) = 2T(n/2) + c·nc·n ∈∈ O(n log n) Promedio 1 n−1 2 n−1 T (n) = ∑[]T (n − i) +T i)( + cn = ∑T i)( + cn∈O(nlog n) n i=1 n i=1 3535 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 (“(“heapheap”).”). Heapsort O(n log n) 3636 HeapsortHeapsort:: Eficiencia 1.1. 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.2. 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)n).. Por tanto, el heapsort es O(n log nn).). 3737 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, ordena el vector (Donald Shell, 1959). 3838 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, ordena el vector (Donald Shell, 1959). 22 22 Inserción O(n ))Shellsort O(nlog n)n) 3939 Bucket sort & Binsort Se divide el array en un conjunto de “urnas” y cada urna se ordena por separado: O(n 22)) Bajo ciertas condiciones (claves entre 0 y NN 11 sin duplicados), la ordenación se puede hacer en O(n): void binSort ((intint[][] v) {{ for ((intint i = 0; i < v.lengthv.length;; i++) while (v[i] != i) { int tmp = v[v[i]]; v[v[i]] = v[i]; v[i] = tmptmp;; }} 4040 }} Otros algoritmos Radix sort Histogram sort Counting sort = ultra sort = mathsort Tally sort Pigeonhole sort Bead sort Timsort Smoothsort …… 4141 Resumen Burbuja Selección 4242 Resumen Inserción Shellsort 4343 Resumen Heapsort Quicksort 4444 Resumen TimsortTimsort:: Mergesort + Ordenación por inserción 4545