Lectura ORDENACIÓN DE ARREGLOS Con frecuencia se requiere clasificar u ordenar los elementos de un vector (arreglo unidimensional) en algún orden en particular. Por ejemplo, ordenar un conjunto de números en orden creciente o una lista de nombres en orden alfabético. Por ser la clasificación de datos una operación tan frecuente en programas de computadoras se han diseñado una gran cantidad de algoritmos para clasificar con eficacia y rapidez. La elección de un determinado algoritmo depende d e l t a m a ñ o d e l a r r e g l o a clasificar, el tipo de datos y la cantidad de memoria disponible. En esta lectura se explicarán los métodos de ordenación (en orden ascendente) aplicados a vectores, pero se pueden extender a matrices (arreglos bidimensionales) multidimensionales considerando la ordenación respecto de una fila o una columna. y Los métodos de ordenación más simples y clásicos son: Ordenación por Selección Ordenación por Inserción Ordenación por Burbuja Otros más complejos son: Ordenación Rápida (quicksort) Método de Shell Ordenación por Selección Este método se basa en buscar el elemento menor el vector y colocarlo en la primera posición. Luego se busca el segundo elemento más pequeño y se coloca en la segunda posición, y así sucesivamente. El algoritmo es como sigue: Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003. 2 Ordenación y Búsqueda Selección desde i = 1 hasta (n-1) buscar el menor elemento de v ubicado desde i hasta n intercambiar menor con v[i] para ubicarlo en la posición i finDesde Para aclarar el algoritmo, consideremos esta lista de valores almacenadas en el arreglo V de seis elementos (n = 6): 98 96 16 90 120 80 Para i = 1, el menor desde i hasta n es 16 y lo intercambiamos con el de la posición i (98) 16 96 98 90 120 80 Para i = 2, el menor desde i hasta n es 80 y lo intercambiamos con el de la posición i (96) 16 80 98 90 120 96 Para i = 3, el menor desde i hasta n es 90 y lo intercambiamos con el de la posición i (98) 16 80 90 98 120 96 Para i = 4, el menor desde i hasta n es 96 y lo intercambiamos con el de la posición i (98) 16 80 90 96 120 98 Para i = 5, el menor desde i hasta n es 98 y lo intercambiamos con el de la posición i (120) 16 80 90 96 98 120 Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003. 3 Ordenación y Búsqueda Finalmente obtenemos el vector ordenado A continuación, se muestra un método de ordenación por selección en Java: static void ordenSelec(double []v , int n){ double temp; int posMenor; for(int i = 1; i < (n-1); i++){ // busca el menor elemento de v desde i hasta n-1 posMenor = i; for(int j = i + 1; j < n; j++ ) if (v[j] < v[posMenor]) posMenor = j; // intercambia el menor con el de la posición i temp = v[posMenor]; v[posMenor] = v[i]; v[i]=temp; } } la ordenación del ejemplo ordena un vector de double. Si los elementos a ordenar son objetos, entonces < no funcionará y necesitaremos sustituirlo por un método, normalmente llamado menorQue o compare Ordenación Rápida (quicksort) El método quicksort se basa en el hecho de que es más rápido y más fácil ordenar dos listas pequeñas que una grande. Se denomina método de ordenación rápida porque, puede ordenar una lista de datos mucho más rápidamente que cualquiera de los métodos de ordenación estudiados anteriormente. Este método se debe a Hoare. El método se basa en la estrategia típica de divide y vencerás (divide and conquer). La lista a clasificar almacenada en un vector se divide en dos sublistas: una con todos los valores, menores o iguales a un cierto valor específico y otra con todos los valores mayores que ese valor. El valor elegido puede ser cualquier valor arbitrario del vector. Este valor se conoce como p i v o t e . Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003. 4 Ordenación y Búsqueda Consideremos esta lista de valores almacenadas en el arreglo V: 18 11 27 13 9 4 6 En el primer paso, el vector se divide en tres partes. Si se elige como pivote el elemento de la posición central, obtenemos los subvectores VI y VD, donde VI contiene los elementos ubicados a la izquierda del pivote y VD los elementos a la derecha, ambos subvectores sin ordenar. 18 11 27 13 9 4 16 pivote VI VD Luego se recorre el subvector VI desde el extremo izquierdo y se busca un elemento mayor que 13 (se encuentra el 18). A continuación se busca en el subvector VD desde el extremo derecho un valor menor que 13 (se encuentra el 4). 18 11 27 13 9 4 16 18 16 Se intercambian estos dos valores y se obtiene la nueva lista: 4 11 27 13 9 Quicksort se basa en el principio que cualquier intercambio que se realice debe tener lugar a la mayor distancia posible. Así, en lugar de intercambiar elementos adyacentes, se intercambian dos elementos que se encuentren prácticamente en extremos opuestos de la lista. Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003. 5 Ordenación y Búsqueda Se sigue recorriendo el subvector VI y se encuentra un nuevo valor mayor que 13 (el 27), y a continuación se recorre el subvector VD y se encuentra un nuevo valor menor que 13 (el 9). 4 11 27 13 9 18 16 27 18 16 Se intercambian esos dos valores y se obtiene: 4 11 9 13 Al intentar el proceso una vez más se encuentra que no existe ningún valor que esté fuera de lugar. En este punto se ha obtenido que todos los valores a la izquierda sean menores que los que se encuentran a la derecha del pivote. Ninguna de ambas sublistas esta ordenada. El siguiente paso sería aplicar quicksort al subvector de la izquierda (con 9 como pivote) y al subvector de la derecha (con 18 como pivote) y finalmente la lista estará ordenada: 4 9 11 13 16 18 27 En resumen, el método consiste en dividir la lista inicial en cierto lugar y trasladar los elementos más grandes a la derecha y los más pequeños a la izquierda, usando i n t e r c a m b i o s l a r g o s . Hecho esto, nos concentramos sobre cada una de las dos sublistas, haciendo lo mismo, hasta que solo nos quede un elemento de cada una. Quicksort no divide cada lista en dos partes iguales, sino que la divide por la posición donde realizó el último intercambio. Expresado como algoritmo, quicksort es: Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003. 6 Ordenación y Búsqueda Quicksort Si la lista tiene más de un elemento 1. Elegir uno de ellos como pivote (por ejemplo el punto medio) 2. Trasladar a la izquierda los elementos menores que él 3. Trasladar a la derecha los elementos mayores que él 4. Aplicar Quicksort sobre la sublista izquierda 5. Aplicar Quicksort a la sublista derecha Donde el algoritmo para Trasladar es: Trasladar 1. Buscar desde la izquierda con i hasta que V[i] > pivote Hasta que i 2. Buscar desde la derecha con j hasta que V[j] < pivote rebase a j 3. Intercambiar V[i] con V[j] 4. Avanzar i una posición a la derecha y j una posición a la izquierda Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003. 7 Ordenación y Búsqueda En java, un programa Quicksort recursivo será: static elem[] Quicksort(elem v[], int izq, int der){ if (izq < der){ visualizar(v, izq, der); int i = izq; int j = der; int k = (int) ((izq + der) / 2); // obtiene el pivote elem pivote = v[k]; // Trasladar do{ while (v[i].menor(pivote)) i++; //busca v[i] > pivote while (pivote.menor(v[j])) j--; //busca v[j] < pivote if (i <= j){ // intercambia elem t = (elem) v[i].clone(); v[i] = v[j]; v[j] = t; i++; j--; // avanza i a la der. y j a la izq. } } while(i<j); v = Quicksort(v, izq, j); v = Quicksort(v, i, der); } return v; // regresa el arreglo modificado } Fuente: BISHOP Judy. (1999) Eficiencia La necesidad de buscar algoritmos diferentes para resolver el mismo problema, proviene del deseo de obtener mayor velocidad. Hay dos maneras de comparar la eficiencia de algoritmos: una teórica y otra experimental. La velocidad de un algoritmo en forma teórica se determina en base al número de operaciones básicas que tiene que realizar. Solo consideramos como operaciones básicas Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003. Ordenación y Búsqueda 8 las comparaciones y los intercambios, y calcular la eficiencia se reduce a contar el número de ejecuciones de los bucles internos. Análisis de los algoritmos de Ordenamiento Referencias: BISHOP Judy. (1999). Java Fundamentos de Programación DEITEL & Deitel. (1999). C++ como programar. Segunda Edición. Prentice may. JOYANES A. y ZAHONERO, M. (2002). Programación en Java 2. Algoritmos, Estructuras de Datos y Programación Orientada a Objetos. Mc Graw Hill. GREG, Perry. (1993). Aprendiendo Programación Orientada a Objetos con Turbo C++ en 21 Días. Prentice Hall Hispanoamericana, S.A. Universidad de Carabobo. Facultad de Ingeniería. Departamento de Computación. Computación Avanzada. 2003.