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    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“Inplaceplace 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“Inplaceplace 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(n1)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 & 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 NN11 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

  Histogram sort  = ultra sort = mathsort  Tally sort  Pigeonhole sort     ……

4141 Resumen

Burbuja

Selección

4242

Resumen

Inserción

Shellsort

4343 Resumen

Heapsort

Quicksort

4444

Resumen

TimsortTimsort:: Mergesort + Ordenación por inserción

4545