Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática ¿Qué es ordenamiento? Ordenamiento • Es la operación de arreglar los registros de una tabla en algún orden de acuerdo a algún criterio. • El propósito principal de un ordenamiento es el de facilitar la búsqueda. • Ejemplos : Guía telefónica, tablas de contenido, bibliotecas y diccionarios, etc. Mauricio Solar Lorna Figueroa 2008 Universidad Técnica Federico Santa María - Departamento de Informática Ordenamiento • Importancia de mantener orden de datos: Fácil y rápido acceso de los datos. • Criterio para el análisis de un algoritmo: • factores con respecto a qué se desea optimizar: • Espacio de memoria • Tiempo de ejecución Universidad Técnica Federico Santa María - Departamento de Informática Ordenamiento • Al momento de tomar esta decisión se debe investigar: • Con qué equipo de trabajo se cuenta (donde se ejecuta el programa), • Necesidades del cliente (si debe ser rápido porque se atiende a diario muchas personas), • etc. Universidad Técnica Federico Santa María - Departamento de Informática ¿Qué es ordenamiento? • Formalmente: Dado un conjunto de n elementos a1, a2,..., an y una relación de orden total (≤) sobre ellos, el problema del ordenamiento consiste en encontrar una permutación de esos elementos ordenada de forma creciente/decreciente. • El tipo y tamaño de los elementos, así como el dispositivo en donde se encuentran almacenados pueden influir en el método utilizado para ordenarlos. Universidad Técnica Federico Santa María - Departamento de Informática ¿Qué es ordenamiento? • Distintos criterios para clasificar los posibilidad es respecto a su eficiencia: • Θ(n2): Burbuja, Inserción, Selección. • Θ(nlogn): Mezcla, Montículos, Quicksort. • Otros: • Incrementos Θ(n1.25), • Cubetas Θ(n), • Residuos Θ(n). algoritmos, una Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Taxonomía de los algoritmos - internos Tipos de Ordenamiento • Interno : datos a ordenar están localizados en la memoria principal del computador. Î se asume que el tiempo que se requiere para acceder cualquier elemento es el mismo. • Externo : datos a ordenar están localizados en algún dispositivo externo (disco, cinta, cilindro magnético, etc), Î se asume que el tiempo que se requiere para acceder a cualquier elemento depende de la última posición accesada. • Ordenamiento por intercalación 1.- Concatenación directa. 2.- Concatenación merge. • Ordenamiento por calculo de direcciones 1.- Ordenamiento de llaves por calculo de direcciones. Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Taxonomía de los algoritmos - internos • Ordenamiento por intercambio 1.2.3.4.- • Burbuja. Transposición par e impar. Shaker sort (vibración). Quick sort (rápido). Taxonomía de los algoritmos - externos • • • • • Straight merging. Natural merging. Balanced multiway merging. Polyphase sort. Distribution of initial runs. Ordenamiento por selección 1.- Selección directa. 2.- Heap sort. Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de intercambio Taxonomía de los algoritmos - internos • • Ordenamiento por inserción 1.- Inserción directa. 2.- Inserción binaria. 3.- Shell. Ordenamiento por distribución 1.- Base radix. 2.- Conteo. • Los elementos se toman de dos en dos, se comparan y se intercambian si no están en el orden adecuado. • Este proceso se repite hasta que se ha analizado todo el conjunto de elementos y ya no hay intercambios. • • • • Burbuja. Transposición par e impar. Shaker sort (vibración). Quick sort (rápido). Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de selección • Se selecciona o se busca el elemento más pequeño (o más grande) de todo el conjunto de elementos y se coloca en su posición adecuada. • Este proceso se repite para el resto de los elementos hasta que todos son analizados. • Selección directa • Heap sort Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de inserción • Los elementos que van a ser ordenados son considerados uno a la vez. • Cada elemento es insertado en la posición apropiada con respecto al resto de los elementos ya ordenados. • • • • Inserción directa, Shell, Inserción binaria, Hashing Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de enumeración • Cada elemento es comparado con los demás. • En la comparación se cuenta cuántos elementos son más pequeños que el elemento que se está analizando, generando así una enumeración. • El número generado para cada elemento indicará su posición. Universidad Técnica Federico Santa María - Departamento de Informática Taxonomía de los algoritmos • Los métodos simples son: • Inserción (o por inserción directa), selección, burbuja y shell, en dónde el último es una extensión al método de inserción, siendo más rápido. • Los métodos más complejos son: • quick-sort (ordenación rápida) y el heap sort. Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: Burbuja • Pasa por un archivo en forma secuencial varias veces. • Cada paso consiste en comparar un elemento del archivo con su sucesor (x[j] con x[j+i]), e intercambiar los dos elementos si no están en el orden apropiado. • Este algoritmo es de fácil comprensión y programación pero es de los menos eficientes • n-1 pasos y n-i comprobaciones en cada paso. Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: Burbuja • Recorre el arreglo intercambiando los elementos adyacentes que estén desordenados. • Se recorre el arreglo hasta que ya no haya cambios. • toma el elemento mayor y lo va recorriendo de posición en posición hasta ponerlo en su lugar. paso 1: [ Inicializar i al final de arreglo ] for(i = n; i ≥ 1; i--) paso 2: [ Inicializar j desde la segunda posición ] for(j = 2; j ≥ i; j++) paso 3: [ Si a[j-1] es mayor que el que le sigue ] if a[j-1]< a[j] paso 5: [ Los intercambia ] swap(a,j-1,j); paso 6: [ Fin ] Universidad Técnica Federico Santa María - Departamento de Informática Burbuja - implementación void Burbuja ( vector a; int prim, ult) { int i, j; for ( i = prim; i <= ult-1; i++ ) { for ( j = ult; j <= i+1; j-- ) { if ( a[j-1]>a[j] ) swap ( a, j-1, j ); } } } } Universidad Técnica Federico Santa María - Departamento de Informática Burbuja - implementación void burbuja() { int aux; Boolean b = true; byte i = 1, j; while ( (i <= n-1) && (b) ) { b = false; while ((j< n-1) && (b)) { b = false; for (j = 1; j <= n-1; j++) { if (x[j] > [j+1]) { b = true; aux = x[j]; x[j] = x[j+1]; x[j+1] = aux; } } i++; } } Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: Burbuja • En el peor de los casos, el número máximo de revisiones es n-1 y el número de intercambios o comparaciones está dado por (n-1) * (n-1) = n2 - 2n + 1 • En el mejor de los casos, el número de revisiones es mínimo 1 y el ciclo de comparaciones es n-1 • El algoritmo es O(n) en el mejor de los casos y O(n2) en el peor de los casos. • Ventaja: requiere poco espacio adicional • una posición de memoria para el valor para intercambio • Desventaja: utilizar excesivo tiempo de ordenamiento por el número de comparaciones que realiza. Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: Burbuja • Es de complejidad cuadrática. • Es el peor entre los algoritmos de O(n2): Selección, Inserción y Burbuja, no sólo en cuanto al tiempo de ejecución, sino también respecto al número de comparaciones y de intercambios que realiza. • Una posible mejora que puede admitir este algoritmo es el control de la existencia de una pasada sin intercambios; en ese momento el vector estará ordenado. • Mejora: Utilizar una bandera booleana que cambia cuando se realiza algún intercambio, • Permanece sin cambio cuando no cambia ningún valor, • puede truncar el ciclo y terminar el proceso de ordenamiento. Universidad Técnica Federico Santa María - Departamento de Informática Burbuja - ejemplo 1 2 3 4 n = b = i = j = x = aux [20] 10 [10] 20 [40] 40 [30] 30 4 ( n-1 = 3 t, f, t, t, 1, 2, 3 1, 2, 3 2, 3 = 20, 40 10 20 30 40 ) f Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: Par_impar void par_impar( ) { int r, i, j, aux; r = (n+1)/2; for ( j = 1; j <= r; ) { i = 1; while (i<n) { if ( x[i] > x[i+1] ) { aux = x[i]; x[i] = x[i+1]; x[i+1] = aux; i = i+2; } else i = i+2; } } } i = 2; while ( i < n ) { if ( x[i] > x[i+1] ) aux = x[i]; x[i] = x[i+1]; x[i+1] = aux; i = i+2; } else i = i+2; } { Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: Par_impar 1 2 3 4 5 6 [40] [30] [10] [60] [20] [50] 30 40 10 60 20 50 30 10 40 60 20 50 30 10 40 20 60 50 10 30 40 20 60 50 10 30 20 40 60 50 10 30 20 40 50 50 10 20 30 40 50 60 n = 6 r = 3 j = 1,2,3. i =1,3,5,7,2,4,6,1,3,5,7,2,4,6,1,3,5,7,2,4,6 aux = 40,40,60,30,40,60,30 Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: shaker • • La idea básica de este algoritmo consiste en mezclar las dos formas en que se puede realizar el método de la burbuja. En este algoritmo cada pasada tiene dos etapas. 1. En la primera etapa "de derecha a izquierda“: • Se trasladan los elementos más pequeños hacia la parte izquierda del arreglo, almacenando en una variable la posición del último elemento intercambiado. • Las sucesivas pasadas trabajan con los componentes del arreglo comprendidos entre las posiciones almacenadas en las variables. • El tamaño de la variable que almacena el extremo izquierdo del arreglo es mayor que el contenido de la variable que almacena el extremo derecho. Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: shaker void shakersort ( ) { int aux,k,i,r,j; i = 2; r = n; do for ( j = r; j >= i; j--) { if (x[j-1] > x[j]) { aux = x[j-1]; x[j-1] = x[j]; x[j] = aux; k =j; } } i = k+1; k = n; for ( j = i; j <= r; ) { if ( x[j-1] > x[j] ) { aux = x[j-1]; x[j-1] = x[j]; x[j] = aux; k = j; } } r = k-1; while ( i > r ); } Algoritmos de Intercambio: shaker 1 2 3 4 [38] [12] [56] [23] i = r = k = j = aux 38 12 23 56 12 38 23 56 12 23 38 56 2,3 4,2 4,2,3 4,3,2,3,4 = 56,38,38 Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercambio: Quick Sort void quick_sort (int a[ ],int p, int q) { int r; int contador = 1; if (p < q) { contador ++; r = particion(a,p,q); quick_sort(a,p,r); quick_sort(a,r+1,q); } } Universidad Técnica Federico Santa María - Departamento de Informática int particion(int a[ ],int p, int temp q) { int temp, x = a[p], i = p-1, j = q+1, cont = 3; while(1) { j = j-1; cont+=5; while( a[j] > x ) { cont += 2; j--; } i++; while ( a[i] < x ) { cont+=2; i++; } if( i < j ) { cont += 3; temp = a[i]; a[i] = a[j]; a[j] = temp; } else return j; } } Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Selección: Selección directa • Se divide el vector en dos zonas, una ordenada y otra sin ordenar. Inicialmente la zona ordenada está vacía y coincide con la posición 1. • En cada iteración se toma el elemento mínimo de la zona sin ordenar y lo coloca en la zona ordenada, intercambiándolo con el elemento siguiente al último de la zona ordenada. • A continuación aumenta la zona ordenada en un elemento para incluir el que se acaba de añadir y vuelve a comenzar otra iteración. • Para ordenar todo el vector, se debe realizar una iteración por cada elemento nuevo a colocar en la zona ordenada y en cada iteración recorrer toda la zona no ordenada del vector para encontrar el mínimo y ponerlo en la zona ordenada. Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Selección: Selección directa • Encontrar el menor de todos los elementos del arreglo e intercambiarlo con el que está en la primera posición. • Luego el segundo más pequeño, y así sucesivamente hasta ordenar todo el arreglo. paso 1: [ Para cada posición del arreglo ] for (i=1;i<= n;) paso 2: [ Inicializar la posición del menor ] { min = i; paso 3: [ Recorrer todo el arreglo ] for( j = i+1; j <= n;) paso 4: [ Si a[ j ] es menor ] if a[j] < a[min] paso 5: [ Reasigna el menor ] min = j; paso 6: [ Intercambia los datos ] swap(a,min,j) paso 7: [ Fin ] } Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Selección: Selección directa • El arreglo a ordenar es a = [ 'a','s','o','r','t','i','n','g','e','x','a','m','p','l','e' ] • Se empieza por recorrer el arreglo hasta encontrar el menor elemento. En este caso el menor elemento es la primera 'a'. No ocurre ningún cambio. Luego se procede a buscar el siguiente elemento y se encuentra la segunda 'a'. Esta se intercambia con el dato que está en la segunda posición, la 's', quedando así el arreglo después de dos recorridos: a = [ 'a','a','o','r','t','i','n','g','e','x','s','m','p','l','e' ]. • El siguiente elemento, el tercero en orden de menor mayor es la primera 'e', la cual se intercambia con lo que está en la tercera posición, o sea, la 'o'. Le sigue la segunda 's', la cual es intercambiada con la 'r'. El arreglo ahora se ve de la siguiente manera: • a = [ 'a','a','e','e','t','i','n','g','o','x','s','m','p','l','r' ]. • De esta manera se va buscando el elemento que debe ir en la siguiente posición hasta ordenar todo el arreglo. Universidad Técnica Federico Santa María - Departamento de Informática Selección directa - implementación void Seleccion(vector a; int prim, ult) { int i; for ( i=prim; i <= ult-1; i++ ) { Intercambia(a ,i, PosMinimo (a, i, ult) ) } } int PosMinimo(vector a; int i, j ) { // devuelve la posicion del minimo elemento de a[i..j] int pmin, k; pmin = i; for ( k = i+1; k <= j; k++) { if ( a[k] < a[pmin] ) pmin = k; } return pmin; } Universidad Técnica Federico Santa María - Departamento de Informática Selección directa - ejemplo • El arreglo a ordenar es: a = [ 'a', 's', 'o', 'r', 't', 'i', 'n', 'g', 'e', 'x', 'a', 'm', 'p', 'l', 'e' ] • Se empieza por recorrer el arreglo hasta encontrar el menor elemento. • En este caso el menor elemento es la primera 'a' • No ocurre ningún cambio. • Luego se procede a buscar el siguiente elemento y se encuentra la segunda 'a' • Esta se intercambia con el dato que está en la segunda posición, la 's', quedando el arreglo después de dos recorridos: a = [ 'a', 'a', 'o', 'r', 't', 'i', 'n', 'g', 'e', 'x', 's', 'm', 'p', 'l', 'e' ] Universidad Técnica Federico Santa María - Departamento de Informática Selección directa - ejemplo • El siguiente elemento, el tercero en orden de menor mayor es la primera 'e' • se intercambia con lo que está en la tercera posición, la 'o' • Le sigue la segunda 's', • la cual es intercambiada con la 'r'. • El arreglo ahora se ve de la siguiente manera: a = [ 'a', 'a', 'e', 'e', 't', 'i', 'n', 'g', 'o', 'x', 's', 'm', 'p', 'l', 'r' ] • De esta manera se va buscando el elemento que debe ir en la siguiente posición hasta ordenar todo el arreglo. Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Selección directa • En el primer paso del ordenamiento se efectúan n-1 comparaciones, en el segundo n-2 comparaciones, y así sucesivamente. • El total de comparaciones aproximadas, está dado por: n(n-1)/2. • La relación de ordenamiento es O(n)2 para cualquier estado inicial de los elementos del arreglo. • El costo del problema, tanto en el caso peor como en el caso mejor es: O(n) = n2 • Este método se le conoce por el nombre de "EMPUJE HACIA ABAJO", y es recomendable para un número pequeño de elementos. Algoritmos de Selección: Heapsort • El vector debe tener estructura de montículo, es decir, un árbol en el que los hijos de cada nodo son siempre menores que el padre. • De esta forma, no se tiene que recorrer toda la zona desordenada para encontrar el elemento máximo, ya que en este caso la ordenación se realiza en sentido inverso. • La estructura en montículo facilita esta búsqueda y la hace del orden de log(n). • Por lo tanto el costo final será log(n) para cada elemento que se quiera colocar en la zona ordenada, es decir: O(n) = n log(n) Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Selección directa • Es de complejidad cuadrática. • Dado el número de operaciones de comparación e intercambio que realiza, es el más adecuado para ordenar pocos registros de gran tamaño. • Si el tipo base del vector a ordenar no es entero, sino un tipo más complejo (guías telefónicas, índices de libros, historiales hospitalarios, etc.) se debe dar mayor importancia al intercambio de valores que a la comparación entre ellos en la valoración del algoritmo por el costo que suponen. • Analizando el número de intercambios que realiza, es de orden O(n), frente al orden O(n2) de intercambios que presentan los métodos de Inserción o Burbuja. Heapsort - ejemplo • Aplicar HeapSort( ) para ordenar el conjunto de datos, S = { 25, 15, 20, 3, 5, 10 } construir el árbol, y numerar los nodos : 25 1 15 2 3 4 5 Universidad Técnica Federico Santa María - Departamento de Informática 25 15 20 3 5 10 1 5 2 3 4 6 10 6 5 Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Selección: Heapsort • Es un método de ordenamiento por selección. • Heap: es un árbol binario de altura mínima, en que los nodos del nivel más bajo están lo más a la izquierda posible. • La información es almacenada de manera que al recorrer un camino desde la raíz hacia las hojas, los datos se encuentran en orden descendente. • Si se presenta este arreglo resultante como un árbol se observa que cada elemento es el padre de los elementos z[i], z[i+1] puesto que es una estructura con un grupo en el cual j ≤ i/2. • En la segunda parte del procedimiento se realiza el proceso de ordenamiento en el cual se recorre el árbol de tal forma que el resultado es una lista ordenada de elementos. 20 3 Heapsort - ejemplo Verificar la condición de heap k = 6 ; (k = nº de nodos) Intercambiar nodo 1 con nodo 6 : 2 4 3 15 5 2 20 3 5 10 1 Resultado : 25 1 10 6 4 15 3 20 3 25 6 5 5 10 15 20 3 5 25 1 5 2 3 4 6 Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Heapsort - ejemplo Heapsort - ejemplo Revisar y recuperar condición de heap, si no se cumple, entre los nodos 1 y 5: 10 1 k = 4; intercambiar los nodos 1 y 4 : 15 1 Resultado: 15 1 15 2 20 3 2 10 5 2 3 4 25 6 5 5 3 4 20 1 4 3 4 15 5 25 6 5 5 3 5 5 25 1 5 25 6 2 3 4 6 3 5 Resultado: 1 5 5 2 2 10 3 25 6 5 5 10 15 20 25 2 15 10 3 4 4 1 2 3 4 5 6 4 Revisar y recuperar condición de heap, si no se cumple, entre los nodos 1 y 4: 1 10 3 20 10 3 5 15 20 25 1 3 2 4 5 Resultado: 10 1 1 5 15 1 2 5 25 6 20 k = 3; intercambiar los nodos 1 y 3 : Resultado : 3 3 5 5 25 6 20 5 15 3 15 10 3 Heapsort - ejemplo Heapsort - ejemplo 4 6 Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática 15 5 10 1 Resultado : 25 6 20 5 3 4 25 6 20 5 15 2 2 4 3 2 10 3 5 15 10 3 20 25 5 3 1 3 4 3 1 Revisar y recuperar condición de heap, si no se cumple, entre los nodos 1 y 3 : 5 1 k = 5; intercambiar los nodos 1 y 5 : 15 25 6 20 5 Heapsort - ejemplo Heapsort - ejemplo 20 1 10 3 Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática 2 15 4 10 3 20 15 10 3 5 2 10 3 25 6 5 5 Resultado: 2 1 3 20 3 25 6 5 2 10 4 4 3 5 2 3 5 3 3 2 10 3 15 5 20 25 6 4 15 25 6 20 5 25 6 20 15 5 10 3 20 25 1 3 3 4 5 6 5 3 10 15 20 25 1 2 3 4 5 6 6 Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Heapsort - implementación Heapsort - ejemplo Revisar y recuperar condición de heap, si no se cumple, entre los nodos 1 y 2. 5 3 2 4 1 15 10 3 5 20 25 6 5 3 10 15 20 25 1 2 3 4 5 6 void heap_sort(int n; int x[ ] ) { int i, j, k, y; for ( k = 2; k <= n; k++ ) { i = k; y = x[k]; j = i/2; while ( j > 0 ) { if ( y <= x[j] ) { x[i] = y x[i] = x[j]; i = j; j = i/2; } } } Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Heapsort - implementación Heapsort - ejemplo k = 2; intercambiar los nodos 1 y 2 : 5 3 2 4 Resultado : 1 15 10 3 5 2 25 6 20 5 4 1 3 15 10 3 5 25 6 20 3 5 10 15 20 25 1 2 3 4 5 6 Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Heapsort – implementación ver.01 Heapsort - ejemplo El algoritmo finaliza, y los datos están ordenados ascendentemente, siguiendo la numeración de los nodos : 3 2 5 1 10 3 3 5 10 15 20 25 1 2 3 4 15 5 20 25 6 for (k= n; k>= 2; k--) { y = x[k]; x[k] = x[1]; i = 1; j = 2; if ( ( x[3] > x[2] ) && ( k-1 > =3 ) ) { j =3; while (j < =k-1) { if ( x[j] < =y ) { x[i] = y; x[i] = x[j]; i = j; j = 2*i; if ( x[j-1] > x[j] ) j++; } } } 4 5 6 HeapSort( ) { BuildHeap( ); // construir el heap for ( k = n ; k > 1 ; k = k – 1 ) { BuildHeap( ) { Intercambiar( A[ 1 ], A[ k ] ; for ( j = n ; j >= 1 ; j -- ) Heapify(1, k - 1) ; Heapify( j, n) } } } Heapify(j, k) { // hace que A[j : k] cumpla con la condición de heap, suponiendo que A[j+1, k] // la cumple if ( (A[ j ] tiene algún hijo ) && ( algún hijo( no es hoja ) de A[ j ] es mayor que él ) ) { Sea A[ s ] el mayor de los hijos de A[ j ] ; Intercambiar (A[ j ], A[ s ] ) ; Heapify(s, k) ; } } Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Selección: Heapsort • Ordena un conjunto de datos, en tiempo O(n lg n) en el peor caso. • Heapify(j, k) toma tiempo O(lg(k-j) • Equivalentemente, hacer heapify partiendo de un elemento de altura h, toma tiempo O(h). • En BuildHeap hay a lo más n / 2i elementos de altura i. • Si el heap tiene altura total h, el tiempo total ocupado por buildheap es : ⎛ ⎞ ⎞ ⎛ o⎜ ∑ i 2ni ⎟ = o⎜ n∑ 2ii ⎟ = O(n ) ⎝ 0≤i ≤ h ⎠ ⎝ i ≥ 0 ⎠ • En HeapSort( ), el tiempo total, para el peor caso, es: ⎛ O(n ) + O⎜⎜ ∑ lg ⎝ 2≤ j ≤ n ⎞ j ⎟⎟ = O(n lg n ) ⎠ Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Inserción: Inserción directa Universidad Técnica Federico Santa María - Departamento de Informática Inserción directa – Ejemplo • El arreglo a ordenar es: a = [ 'a', 's', 'o', 'r', 't', 'i', 'n', 'g', 'e', 'x', 'a', 'm', 'p', 'l', 'e' ] • El algoritmo recorre el arreglo de izquierda a derecha. • Primero toma el segundo dato, 's' y lo asigna a v; • i toma el valor de la posición actual de v. • Luego compara 's' con lo que hay en la posición j-1, ie, con 'a'. • Debido a que 's' no es menor que 'a' no sucede nada y avanza i. • Ahora v toma el valor 'o' y lo compara con 's', • como es menor, lleva 's' a la posición de la 'o'; • decrementa j, la cual ahora tiene la posición en dónde estaba 's'; Universidad Técnica Federico Santa María - Departamento de Informática Inserción directa – Ejemplo • Toma cada elemento del arreglo y lo compara con los que se encuentran en posiciones anteriores a la de él dentro del arreglo. • Si el elemento con el que se está comparando es mayor que el elemento a ordenar, • se recorre hacia la siguiente posición superior. • Si no, • se detiene el proceso de comparación • el elemento ya está ordenado • y se coloca en su posición • es la siguiente a la del último número con el que se comparó. • compara a 'o' con a[j-1] , es decir, con 'a' • Como no es menor que 'a' sale del for y pone la 'o' en la posición a[j] • El resultado hasta este punto es el arreglo siguiente: a = [ 'a', 'o', 's', 'r', .... ] Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Inserción: Inserción directa • Toma el arreglo de datos a ordenar a[] y modifica las posiciones de sus elementos hasta dejarlos ordenados de menor a mayor. • n representa el número de elementos que contiene a[ ]. paso 1: [Para cada posición del arreglo] for(i = 2; i<= n;i++) paso 2: [ Inicializar v y j ] { v = a[i]; j = i; paso 3: [ Compara v con los anteriores ] while(a[j-1]>v) && (j>1) paso 4: [ Recorre los datos mayores ] { a[j] = a[j-1]; paso 5: [ Decrementa j ] j = j-1; } paso 5: [ Inserta v en su posición ] a[j] = v; • Así se continúa y el resultado final es el arreglo ordenado : a = [ 'a', 'a', 'e', 'e', 'g', 'i', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'x' ] Inserción directa • Si el arreglo inicial está ordenado se hace una comparación en cada paso, O(n). • Si los elementos están ordenados en sentido inverso la relación es O(n)2. • Número de comparaciones: • arreglo ordenado: n-1 • arreglo desordenado: (n-1)*(n/2) • Método muy adecuado para aquellas situaciones en donde se necesita ordenar un vector que está casi ordenado, como suele suceder en aquellas aplicaciones de inserción de elementos en bancos de datos previamente ordenados cuya ordenación total se realiza periódicamente. Universidad Técnica Federico Santa María - Departamento de Informática Inserción directa - implementación void Insercion (vector a; int prim, ul) { int i, j, x; for ( i = prim+1; i <= ult; i++ ) { x = a[i]; j = i-1; while ( ( j >= prim ) && (x < a[j] ) ) { a[j+1] = a[j]; j--; } a[j+1] = x; } } Universidad Técnica Federico Santa María - Departamento de Informática Inserción binaria - implementación Inserción_binaria( int x[] ) { int a, i, j,m, s, r; for ( i = 2; i <= n; ) { a = x[i]; s = 1; r = i; while (s < r) { m =(s+r) div 2; if(x[m] < a) s = m+1; else r = m; } for( j = i; j > r+1 ; j-- ) x[j] = x[j-1]; } x[r] = a; } } Universidad Técnica Federico Santa María - Departamento de Informática Inserción binaria • Similar a la inserción directa, realiza el mismo número de pasos, toma la misma variable auxiliar ´a´ e inicializa 2 variables. • El ordenamiento se lleva a cabo de la siguiente manera: Saca mitad de s y r, compara el contenido de la mitad con el valor de “a" si es más grande, hace más grande el límite superior de lo contrario, hace más grande el límite inferior. • Este proceso se realiza mientras el límite inferior sea menor que el superior, después se realiza un ciclo decrementado donde los números mayores se van bajando, y por ultimo se asignan el valor de “a", al contenido del rango “r". Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Inserción: Shell • También llamado Ordenamiento de disminución incremental. • Ordena subgrupos de elementos separados k unidades (respecto de su posición en el arreglo) del arreglo original. • El valor k es llamado incremento. • Después de que los primeros k subgrupos han sido ordenados (generalmente utilizando insercion directa), se escoge un nuevo valor de k más pequeño, y el arreglo es de nuevo dividido entre el nuevo conjunto de subgrupos. • Cada uno de los subgrupos mayores es ordenado y el proceso se repite de nuevo con un valor más pequeño de k. • Eventualmente el valor de k llega a ser 1, de tal manera que el subgrupo consiste de todo el arreglo ya casi ordenado. • Al principio del proceso se escoge la secuencia de decrecimiento de incrementos; el último valor debe ser 1. Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Inserción: Shell • Es como hacer un ordenamiento de burbuja pero comparando e intercambiando elementos. • Cuando el incremento toma un valor 1, todos los elementos pasan a formar parte del subgrupo y se aplica inserción directa. • El método se basa en tomar como salto N/2 (siendo N el número de elementos) y luego se va reduciendo a la mitad en cada repetición hasta que el salto o distancia vale 1. • Su complejidad es difícil de calcular y depende mucho de la secuencia de incrementos que utilice. • En general este método es el escogido para muchas aplicaciones reales por ser muy simple teniendo un tiempo de ejecución aceptable incluso para grandes valores de n. Universidad Técnica Federico Santa María - Departamento de Informática Shell - implementación void Shell( int n; int x[ ] ) { int aux, salto = n/2, i, j, k; while (salto > 0) { for ( i = salto +1; i <= n; i++ ) { j = i - salto; while ( j > 0 ) { n = j + salto; if ( x[j] <= x[k] ) j = 0; else { aux = x[j]; x[j] = x[k]; x[k] = aux; } j = j - salto; } } salto = salto /2; } } Universidad Técnica Federico Santa María - Departamento de Informática Mergesort - implementación Shell - ejemplo • Para el arreglo a = [ 6, 1, 5, 2, 3, 4, 0 ], se tiene el siguiente recorrido: Recorrido Salto Lista Ordenada Intercambio 1 3 2, 1, 4, 0, 3, 5, 6 (6,2), (5,4), (6,0) 2 3 4 3 3 1 0, 1, 4, 2, 3, 5, 6 0, 1, 4, 2, 3, 5, 6 0, 1, 2, 3, 4, 5, 6 (2,0) Ninguno (4,2), (4,3) 5 1 0, 1, 2, 3, 4, 5, 6 Ninguno Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos por distribución: Método de conteo void conteo(int n, int x[ ] ) { int s[n], p, i, j; for ( i = 1; i <= n; i++ ) { p =1; for( j = 1; j <= n; j++) if (x[i] > x[j]) p++; s[p]=x[i]; } } 1 [20] [1] 2 [15] [8] 3 [8] [15] 4 [1] [20] i = 1, 2, 3, 4 p = 1, 2, 3, 4 |1,2,3,4| |1,2,3 | |1, 2 | j = 1, 2, 3, 4 |1,2,3,4| |1,2,3,4| |1,2,3,4| Universidad Técnica Federico Santa María - Departamento de Informática |1 | Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Intercalación: Mergesort • Utiliza la técnica de Divide y Vencerás. • Su estrategia consiste en dividir el vector en dos subvectores, ordenarlos mediante llamadas recursivas, y finalmente combinar los dos subvectores ya ordenados. void Mezcla( vector a,b; int prim,ult ) { // utiliza el vector b como auxiliar para realizar la mezcla int mitad; if ( prim < ult ) { mitad = ( prim + ult ) / 2; Mezcla ( a, b, prim, mitad ); Mezcla ( a, b, mitad+1, ult ); Combinar ( a, b, prim, mitad, mitad+1 ,ult ); } } Universidad Técnica Federico Santa María - Departamento de Informática Mergesort - implementación void Combinar(vector a, b; int p1,u1,p2,u2) { // mezcla ordenadamente los subvectores a[p1..u1] y a[p2..u2] suponiendo que están ya // ordenados y que son consecutivos (p2 = u1+1), utilizando el vector auxiliar b. int i1, i2, k; if ( ( p1 > u1) || ( p2 > u2 ) ) exit (1); for ( k = p1; k <= u2; k++ ) { b[k] = a[k]; } // volcamos a en b i1 = p1; i2 = p2; // cada indice se encarga de un subvector for ( k = p1; k <= u2; k++ ) { if ( b[i1] <= b[i2] ) { else { a[k] = b[i1]; a[k] = b[i2]; if ( i1 < u1 ) i1++; if ( i2 < u2 ) i2++; else b[i1] = max_int; else b[i2] = max_int; } } } } Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos por intercalación: merge void Merge( int an,ab,cn ) { int apa =1, apb =1, apc =1; if ( ( an + bn ) > cn ) printf("ERROR"); else { while( (apa <= an) && (apb <= bn) ) { if a[apa] < b[apb]) { c[apc] = a[apa]; apa++; } else { c[apc] = b[apb]; apb++; } apc++; } while( apa <= an ) { c[apc] = a[apa]; apa ++; apc ++; } while (apb <= bn) { c[apc] =b[apb]; apb++; apc++; } } } Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Ordenación por Cubetas (Binsort) Algoritmos de Intercalación: Mergesort • Ordena n elementos en tiempo Θ(nlogn) en cualquiera de los casos (peor, mejor o medio). • Sin embargo tiene una complejidad espacial, en cuanto a memoria, mayor que los demás (del orden de n). • Otras versiones de este algoritmo no utilizan el vector auxiliar b, sino que trabajan sobre el propio vector a ordenar, combinando sobre él los subvectores obtenidos de las etapas anteriores. • Consigue ahorrar espacio (un vector auxiliar), pero complica el código del algoritmo resultante. void Cubetas ( vector a ) { int i; for ( i = 1; i <= n; i++ ) { while ( a[i] != i ) { swap ( a, i, a[i] ); } } } Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Ordenación por Residuos (Radix) Algoritmos de Intercalación: Mergesort • Se adapta muy bien a distintas circunstancias, por lo que es comúnmente utilizado no sólo para la ordenación de vectores. • Por ejemplo, el método puede ser también implementado de forma que el acceso a los datos se realice de forma secuencial, por lo que hay diversas estructuras (como las listas enlazadas) para las que es especialmente apropiado. • También se utiliza para realizar ordenación externa, en donde el vector a ordenar reside en dispositivos externos de acceso secuencial (i.e. archivos). • • • Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Ordenación por Residuos (Radix) Ordenación por Cubetas (Binsort) • Se supone que los datos a ordenar son números naturales, todos distintos y comprendidos en el intervalo [1,n]. • Es decir, el problema es ordenar un vector con los n primeros números naturales. • Bajo esas circunstancias es posible implementar un algoritmo de complejidad temporal O(n): ordenación por Cubetas, • en cada iteración se sitúa un elemento en su posición definitiva. Puede utilizarse cuando los valores a ordenar están compuestos por secuencias de letras o dígitos que admiten un orden lexicográfico. El método consiste en definir k colas (numeradas de 0 a k–1) siendo k los posibles valores que puede tomar cada uno de los dígitos que componen la secuencia. Una vez tengamos las colas habría que repetir, para i a partir de 0 y hasta llegar al número máximo de dígitos o letras de nuestras cadenas: 1. Distribuir los elementos en las colas en función del dígito i. 2. Extraer ordenada y consecutivamente los elementos de las colas, introduciéndolos de nuevo en el vector. • • • • Sea el vector: [0, 1, 81, 64, 23, 27, 4, 25, 36, 16, 9, 49]. En este caso se trata de números naturales en base 10, que son secuencias de dígitos. Se necesitan 10 colas. • Cada uno de los dígitos puede tomar 10 valores (del 0 al 9) En la primera pasada se introducen los elementos en las colas de acuerdo a su dígito menos significativo: Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Ordenación por Residuos (Radix) • Extraer ordenada y sucesivamente los valores, obteniendo el vector: [0, 81, 1, 23, 4, 64, 25, 16, 36, 27, 49, 9]. Volver a realizar otra pasada, esta vez tomando el segundo dígito menos significativo: • • Búsqueda Mauricio Solar Lorna Figueroa Volviendo a extraer ordenada y sucesivamente los valores se obtiene el vector: [0, 1, 4, 9, 16, 23, 25, 27, 36, 49, 64, 81]. Como el máximo de dígitos de los números a ordenar era dos, con dos pasadas es suficiente. • Universidad Técnica Federico Santa María - Departamento de Informática Ordenación por Residuos (Radix) typedef struct colaitem { vector elems; int cont } void Residuos(vector a; int B, prim, ult) { int i, j, k, h, digito iter; boolean sigo; colaitem colas[MAXB-1]; iter = 1; // iter va acumulando B1,B2,B3,... do // para cada uno de los digitos for ( i = 0; i <= B-1; i++ ) // inicializar las colas colas[i].cont = 1; // primera posicion libre // clasificacion de los elementos en las colas sigo = false; // indica si quedan numeros con mas digitos for ( i = prim; i <= ult; i++ ) { sigo = ( ( a[i] / iter ) >= int( B ) ) || sigo; Universidad Técnica Federico Santa María - Departamento de Informática Ordenación por Residuos (Radix) digito = ( a[i] / iter ) % int(B); // num cola colas[digito].elems[colas[digito].cont] = a[i]; colas[digito].cont++; // inserta a[i] en su cola } } iter = iter*int(B); j = prim; // ahora volcamos las colas sobre el vector for ( i = 0; i<= B-1; i++ ) { h = colas[i].cont-1; // num de elementos en esa cola for ( k = 1; k <= h; k++ ) { a[j] = colas[i].elems[k]; j++; } } while ( ! Sigo ); 2008 Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda • La recuperación de información es una de las más importantes aplicaciones de los computadores. • Dado un nombre entregar un número telefónico asociado. • Dado un número o nombre se deben encontrar los registros personales de dicho nombre o clave. • En estos ejemplos se está dando una parte de la información, la llave (o clave) y se está preguntando para encontrar un registro que contiene más información asociada con la llave. • La búsqueda de llaves para encontrar registros es a veces la acción que requiere más tiempo en un programa. Universidad Técnica Federico Santa María - Departamento de Informática Clasificación de Técnicas de Búsqueda • Búsqueda interna. • Los registros se mantienen dentro de la memoria del computador. • Búsqueda externa. • Hay muchos registros y cada uno muy grande o extenso y es necesario almacenarlos en archivos o en medios externos. Universidad Técnica Federico Santa María - Departamento de Informática Universidad Técnica Federico Santa María - Departamento de Informática Clasificación de Técnicas de Búsqueda • Búsqueda por comparación de llaves. • Se tiene la búsqueda secuencial, que es una técnica de búsqueda que mejora la eficiencia de un archivo ordenado pero requiere mayor espacio. • Búsqueda por transformación de llaves. • El valor de la llave se transforma en un índice de una tabla para obtener una dirección. Universidad Técnica Federico Santa María - Departamento de Informática Algoritmos de Búsqueda • Búsqueda por comparación de llaves • Secuencial • Secuencial encadenada • Secuencial indexada • Secuencial binaria • Árbol binario de búsqueda • …. • Búsqueda por transformación de llaves • Funciones hash • Método de la división • Método del cuadrado • Método de pliegue • ….. Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda por comparación de llaves Búsqueda por comparación de llaves 2. Búsqueda secuencial encadenada. • • • Almacena una tabla o archivo como lista encadenada. Ventaja: el tamaño de la tabla puede ser aumentada únicamente de acuerdo a los requerimientos. Asume que la tabla está organizada como una lista encadenada lineal. Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda por comparación de llaves 2.- ALGORITMO DE BUSQUEDA BINARIA. • Este método es el más eficiente en un tabla o archivo secuencial. • El argumento de búsqueda es comparado con la llave del elemento central de la tabla, si estos son iguales entonces termina la búsqueda, si no, continua la búsqueda con la parte superior o inferior de la tabla siguiendo los mismos pasos. • Válido exclusivamente para vectores ordenados. • Termina si se encuentra el valor buscado o si el tamaño del intervalo de búsqueda queda anulado. • En los casos en que existan repeticiones en el vector, del valor buscado, obtendrá uno de ellos aleatoriamente según los lugares que ocupen, los cuales necesariamente son consecutivos. Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda por comparación de llaves 1. Búsqueda secuencial. int A_SECUENCIAL( int llave; int k [ ] ) { int i = 1, n; boolean f = false; while( ( i<=n ) && ( ! ( f ) ) if ( llave == k[i] ) { posic = i; f = true; } else i++; if ( ! f ) posic = 0; return posic; } #include <stdio.h> void main (void) { int vector [100], x, enc, i, centro, izqda, dcha; for (i = 0; i <= 99; i++) // ingreso de datos al arreglo vector[i] = i * 2; x = i / 2; // Escritura en pantalla del vector ordenado printf ("\n\nVector:\n"); for (i = 0; i < 100; i++) printf ("%d\t", vector[i]); Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda por comparación de llaves printf ("\nValor a buscar: %d", x); // Búsqueda binaria en vector ordenado enc = 0; izqda = 0; dcha = 99; while (! enc && izqda <= dcha) { centro = (izqda + dcha) / 2; if (x < vector[centro]) dcha = centro - 1; else if (x > vector[centro]) izqda = centro + 1; else enc = 1; } Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda por comparación de llaves // Escritura en pantalla del vector ordenado if (enc) printf("\n%d encontrado en índice %d ", x, centro); else printf ("\n\nNo existe el valor %d en el vector.", x); getch (); } Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda por comparación de llaves // Implementación recursiva del algoritmo de Búsqueda Binaria #define FALSE 0 #define TRUE 1 int búsqueda( int vec[ ], int elem, int limiteInf, int limiteSup ) { int medio; } if ( limiteInf > limiteSup ) return FALSE; else if(vec[ medio = (limiteInf + limiteSup +1 ) / 2 ] == elem ) return TRUE; else if ( elem < vec[ medio ] ) return búsqueda( vec, elem, limiteInf, medio-1 ); else return búsqueda( vec, elem, medio+1, limiteSup ); Universidad Técnica Federico Santa María - Departamento de Informática Búsqueda por comparación de llaves ALGORITMO FIBONACCI: • Algoritmo de búsqueda es para un arreglo ordenado que utiliza la secuencia numérica de Fibonacci como parte del proceso. • Se utiliza un arreglo que contiene los números Fibonacci. • La secuencia Fibonacci consiste en que cada elemento es la suma de los dos elementos anteriores. 0, 1, 1, 2, 3, 5, 8, 13,............. Universidad Técnica Federico Santa María - Departamento de Informática int FIBONACCI( int llave,n, K[ ], FIB[ ] ) { int T, J = 1, mitad = 1/n; boolean fin; while((FIB[J] != K[mitad] ) && ( ! fin) ) if ((mitad <= 0) || (llave> K[mitad])) if ( F1 = = 1 ) fin = true else { mitad = mitad + F2; F1 = F1 - F2; F2 = F2 - F1; } else { if (F2 == 0 ) fin = true; else { mitad = mitad - F2; T = F1 - F2; F2 = T; } if ( fin ) return 0; else return mitad; } Universidad Técnica Federico Santa María - Departamento de Informática Referencias • Apuntes y notas personales • ¿Qué es ordenamiento?; Raiger Murillo Moreno. • Aho, J.E. Hopcroft y J. D. Ullman, Data structures and algorithms. • T. Cormen, C. Leiserson y R. Rivest, Introduction to Algorithms. • H. R. Lewis y L. Denenderg, Data Structures and Their Algortihms. • D. E. Knuth, The Art of Computer Programing, Vol. 1, Fundamental Algorithm, y Vol. 3, Sorting and Searching. • R. Sedgewick, Algorithms. • G. H. Gonnet y R. Baeza-Yates, Handbook of Algorithms and Data Structure.