Estructuras de datos Estructuras de datos Introducción Básicos Los ordenamientos son una tarea frecuente y fundamental en la programación de sistemas. ! Grandes cantidades de datos se almacenan para su posterior consulta. ! Las búsquedas más eficientes se basan en conjuntos de datos ordenados. ! Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! Los tres métodos básicos son: Burbuja – Inserción – Selección – Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Básicos Básicos template <class T> void burbuja(T *a, int tam){ int i, j; for( i = 0; i < tam; i ++) //n pasadas for( j = tam-1; j >= i + 1; j--) //n comparaciones if(a[j-1] > a[j]) intercambia(a, j-1, j); } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos template <class T> void intercambia(T *a, int i, int j){ T temp; temp = a[i]; a[i] = a[j]; a[j] = temp; } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 1 Estructuras de datos Estructuras de datos Básicos Básicos template <class T> void insercion(T *a, int tam){ int i, j; T v; for( i = 0; i < tam; i ++){ v = a[i]; //elemento a insertar for( j = i; j > 0; j--){ if(a[j-1] <= v) break; //los j menores ya estan ordenados a[j] = a[j-1]; //recorrer los mayores para hacer la inserción } a[j] = v; //insertar el elemento } } template <class T> void seleccion(T *a, int tam){ int i, j; for( i = 0; i < tam-1; i ++) for( j = i + 1; j < tam; j++) if(a[i] > a[j]) intercambia(a, i, j); //busca el //elemento menor en el resto no ordenado } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! ! Estructuras de datos Estructuras de datos Básicos Básicos Todos los métodos de ordenamiento pueden describirse en términos de comparaciones e intercambios. Los tres métodos básicos tienen un rendimiento cuadrático para el peor de los casos en cuanto al número de comparaciones. El peor caso es una lista en orden inverso. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! El método de la burbuja puede mejorarse con la ayuda de un centinela que verifique si se han realizado intercambios en alguna pasada intermedia. Una técnica útil en la selección consiste en guardar la posición del elemento menor y hacer un solo intercambio al final de la pasada. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 2 ! ! Estructuras de datos Estructuras de datos Shellsort Shellsort Métodos más elaborados usan la técnica de divide y venceras para lograr reducir el tiempo de ordenamiento. El más simple de estos métodos es el shellsort. Básicamente aprovecha que el ordenamiento por inserción mejora su eficiencia con arreglos parcialmente ordenados. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! ! ! template <class T> void shellsort(T *a, int tam){ int i, j, h; T v; for(h = 1; h <= tam/9; h = h*3 + 1); //generador de secuencias(1, 4, 13, 40, 121, 364…) for( ; h >0; h /= 3) //controla los h-ordenamientos for( i = h; i < tam; i ++){ //ordenamiento por inserción v = a[i]; for( j = i ; j >= h; j-=h){ if(a[j - h] <= v) break; a[j] = a[j-h]; } a[j] = v; } } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Shellsort Mergesort Sus puntos a resaltar son la secuencia de preordenamientos a distancias h. Dicha secuencia es empírica y se sabe que el método es dependiente de la misma. La peor secuencia conocida es aquella de potencias de 2. Todas las secuencias deben terminar en 1. Su rendimiento es aprox. O(N1.25). Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! ! Otro método muy simple que usa la técnica de divide y vencerás es el ordenamiento por fusión o mergesort. Se basa en fusionar dos subarreglos ya ordenados en uno mayor. Se ordena eligiendo al menor elemento de los dos subarreglos hasta que ambos quedan vacios. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 3 ! ! Estructuras de datos Estructuras de datos Mergesort Mergesort El método de particionamiento es binario. Divide el arreglo y subarreglos a la mitad cada vez, deteniéndose en subarreglos de tamaño uno. Los arreglos de tamaño uno ya estan ordenados. A partir de ellos se comienza la fusión creando arreglos ordenados que se acercan en tamaño al arreglo original. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! Sus incovenientes son: – – ! uso de un arreglo auxiliar su naturaleza recursiva. La implementación de dicho algoritmo tiene una eficiencia temporal de O(NlogN). Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Mergesort Fusión externa template <class T> void mergesort(T *a; int izq; int der){ int i, j, k, m; T b[tam]; if( der > izq){ //mas de un elemento m = (izq + der) / 2; mergesort(a, izq, m); //mitad izquierda mergesort(a, m+1, der); //mitad derecha for(i = izq; i <= der; i++) b[i] = a[i]; //copia mitades a fusionar for(i = izq, j = izq, k = m+1; i <= der; i++) // fusionar ambas mitades if( j <= m && k <= der) //elegir al menor de los dos a[i] = (b[j] < b[k]) ? b[j++] : b[k++]; else //uno de los arreglos ya esta vacio a[i] = (k > der) ? b[j++] : b[k++]; } } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! El ordenamiento por fusión puede extenderse a ordenar datos en memoria secundaria. El problema del ordenamiento externo consiste en los siguientes puntos: – – El acceso al medio es lento y a veces secuencial. La memoria secundaria es mucho mayor a la memoria principal. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 4 Estructuras de datos Estructuras de datos Fusión externa Fusión externa La técnica más recomendada consiste en usar la fusión multivias. ! Consiste en dividir el archivo en partes que se puedan ordenar en memoria interna para luego fusionarlas. ! ! ! ! ! ! Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! Considere el siguiente ejemplo. Se tiene espacio en memoria para almacenar solo tres registros. Se usarán tres vías o subarchivos para hacer la fusión. Se dispone de un archivo de entrada con 25 registros. EJEMPLODEORDENACIONFUSION. Cada carácter representa un registro. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Fusión externa Fusión externa Leer las tres primeras letras EJE y ordenar EEJ, escribirlas en la cinta 1. Tomar las siguientes 3 ordenar y escribirlos en la cinta 2. Los siguientes 3 repetir el proceso con las cintas 3, 1, 2, ...etc hasta vaciar el archivo original. En la siguiente lámina se muestra el resultado de la primera pasada. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Cinta 1 EEJ-DOR-FNU Cinta 2 LMP-AEN-IOS Cinta 3 DEO-CIO-N Cinta 4 Cinta 5 Cinta 6 A este proceso seguiría el de la fusión con subarchivos de tamaño 3. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 5 Estructuras de datos Estructuras de datos Fusión externa Fusión externa El resultado de la segunda pasada sobre el archivo a ordenar sería como sigue: Cinta 1 Cinta 2 Cinta 3 Cinta 4 DEEEJLMOPCinta 5 ACDEINOORCinta 6 FINNOSUA este proceso seguiría el de la fusión con subarchivos de tamaño 9. Este ejemplo concluiría a la tercer pasada. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! ! ! ! Se nota el inconveniente de tener que usar 3 subarchivos más para realizar la fusión. El proceso puede mejorarse si se usan montículos para realizar la fusión en lugar de una selección simple. Pueden usarse cualquier número permitido de vías tomando en cuenta que se necesitarán el doble de archivos temporales. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Heapsort Heapsort Otro de los métodos clásicos de ordenamiento es el ordenamiento por montículos o heapsort. Utiliza la estructura de montículos aprovechando que su implementación basada en árboles binarios tiene una eficiencia logarítmica para la mayoría de sus operaciones. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 1 2 4 5 9 8 5 7 6 3 6 3 2 7 9 8 7 5 6 3 2 Un heap descendente y su representación por medio de un arreglo. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 6 ! ! ! ! Estructuras de datos Estructuras de datos Heapsort Heapsort Nótese que los hijos son menores a su padre en un heap descendente. Los numeros fuera de los círculos lo relacionan con las posiciones del arreglo. Nótese también que un padre esta a la mitad del arreglo con respecto a sus hijos. Esto último hace las operaciones de tiempo logarítmico cuando es necesario hacer intercambios. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos template <class T> void subirmonticulo(int k){ T v; v = a[k]; while(a[(k-1)/2] <= v ){ a[k] = a[(k-1)/2]; //sustituir por el padre k = (k-1)/2; if ( k < 1) break; // no sobrepasar el índice 0 } a[k] = v; //acomodar en el lugar correcto } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Heapsort Heapsort void insertar(T v){ if(ult < TAM){ //no sobrepasar el final del arreglo a[ult++] = v; //considerar que la primera vez ult = 0 subirmonticulo(ult-1); } } T suprimir(){ T v = a[0]; //eliminar el más grade a[0] = a[--ult]; //sustituirlo por el ultimo del montículo bajarmonticulo(0); //restablecer el montículo return v; } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos template <class T> void bajarmonticulo(int k){ T v = a[k]; //guardar elemento a mover while(k <= (ult-1)/2){ //un nivel antes de las hojas j = 2*k + 1; //hijo izquierdo de k (si k inicia en 0) if(j < (ult-1)) //k tiene mas de un hijo if(a[j] < a[j+1]) j++; //el hijo derecho es mayor if(v >= a[j]) break; //se llego al final del montículo a[k] = a[j]; //sustituir por el mayor de los hijos k = j; } a[k] = v; //colocar en el lugar correcto } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 7 Estructuras de datos Estructuras de datos Heapsort Heapsort Las operaciones subir y bajar montículo estan diseñadas para restablecer el montículo. ! Dichas operaciones usan recorridos del montículo de padres a hijos o viceversa. ! Estos recorridos son de tiempo logarítmico. ! Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! Un ordenamiento simple usaría las operaciones insertar y suprimir. template <class T> void heapsort(T *b, int tam){ //ordena arreglo de tamaño tam int i; crearmonticulo(tam); //crea un montículo de tamaño tam for( i = 0; i < tam; i++) insertar(b[i]); //inserta en un montículo for(i = tam – 1; i >= 0; i--) b[i] = suprimir(); //suprime en orden inverso } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Heapsort Heapsort template <class T> void heapsort(T *a, int tam){ int k; for( k = (tam-1)/2; k >= 0; k --) //no considerar los montículos de tam 1 bajarmonticulo(a, tam, k); //construir el montículo ult = tam; //señala la última posición del arreglo while(ult > 0){ intercambio(a, 0, ult-1); //poner el mayor al último bajarmonticulo(a, --ult, 0); //restablece sin considerar al último } //elemento del arreglo (ya quedo en su lugar) } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos La eficiencia del heapsort esta entre 2NlogN y 1.5NlogN. ! En la segunda implementación se mejora la eficiencia temporal y espacial. ! Es un buen método que aprovecha las virtudes de los montículos. ! Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 8 ! ! ! Estructuras de datos Estructuras de datos Quicksort Quicksort Sin lugar a dudas el más estudiado y comentado de los métodos de ordenamiento es el ordenamiento rápido o quicksort. Este aprovecha la técnica de divide y vencerás además de una selección doble. Usa un pivote para realizar las particiones y colocar los menores antes del pivote y los mayores después. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos ! ! ! Este método además es capaz de localizar la posición exacta de un elemento. Su único punto débil es que no puede detectar que un arreglo o subarreglo ya fue ordenado. Esto último da pie a mejoras. Una de ellas consiste en trabajar combinado con un método de inserción a partir de subarreglos. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos Estructuras de datos Estructuras de datos Quicksort Quicksort template <class T> void quicksort(Arreglo<T> &a, int izq, int der){ int i, j; T v, temp; if( der > izq){ v = a[der]; //usar como pivote el extremo derecho de la partición for(i = izq-1, j = der; ; ){ while(a[++i] < v ); //buscar la posición del pivote while(a[--j] > v && j > 0); if( j <= i) break; //ya se encontro la posicion del pivote intercambio(a, i, j); //menores a la izquierda y mayores a la derecha } intercambio(a, i, der); //mover el pivote a su posición quicksort(a, izq, i-1); //ordenar elementos a la izquierda del pivote quicksort(a, i+1, der); //ordenar elementos a la derecha del pivote } } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos template <class T> void selecc(T *a, int tam, int k){ int i, j, izq, der; T v; izq = 0; der = tam –1; while(der > izq){ for(i = izq-1, j = der, v = a[der]; ; ){ //crear particiones while(a[++i] < v); while(a[--j] < v && j > 0); if ( i >= j) break; intercambio(a, i, j); } intercambio(a, i, der); //mover pivote a su posición if( i >= k) der = i – 1; //restringir el espacio de búsqueda if(i <= k) izq = i +1; } } Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 9 Estructuras de datos Otros métodos ! Existen otros métodos dignos de mención como: – – ! Ordenamiento por urnas o binsort. Ordenamiento por residuos o radixsort. También pueden usarse métodos de ordenamiento indirecto por medio de un arreglo de apuntadores que minimicen los intercambios de registros. Ing. Ordenamientos Ing.Jorge JorgeA. A.Hernández HernándezP.: P.:Ordenamientos 10