Algoritmo, Ordenacion y Búsqueda

12,006 views

Published on

1 Comment
2 Likes
Statistics
Notes
  • Hola, me ha parecido muy buena tu aportación, estoy estudiando eso ahora mismo y me gustaría saber si pudieras facilitarme los datos de la bibliografía para poder estudiar yo de ellos? Muchisimas gracias y buen aporte!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
12,006
On SlideShare
0
From Embeds
0
Number of Embeds
28
Actions
Shares
0
Downloads
282
Comments
1
Likes
2
Embeds 0
No embeds

No notes for slide

Algoritmo, Ordenacion y Búsqueda

  1. 1. Trabajo Práctico “Algoritmos de Ordenación y Búsqueda” Alumno Alvarez Pedro Javier I. Profesor Ángel Luis Vicentín Espacio Curricular Algoritmos y Programación Profesorado en Informática 1º “B” ISFD Dr. Juan Pujol -2013-
  2. 2. Índice. Índice. ........................................................................................................................................... 0 Búsqueda, Clasificación e Intercalación. ................................................................................ 2 Búsqueda................................................................................................................................. 2 Búsqueda lineal o secuencial, la técnica más sencilla. ......................................... 2 Búsqueda de máximos y mínimos. ............................................................................. 4 Búsqueda externa. ........................................................................................................... 8 Búsqueda binaria o dicotómica, la técnica más eficiente. .................................. 10 Clasificación u Ordenación. .................................................................................................... 13 Ordenación por intercambio. .............................................................................................. 14 Ordenación por selección. .................................................................................................. 17 Ordenación por Inserción. ................................................................................................... 21 Algoritmo de ordenación por inserción. .................................................................. 21 Ordenación Shell. ................................................................................................................. 21 Algoritmo de ordenación Shell. .................................................................................. 22 Ordenación Rápida (Quicksort).......................................................................................... 23 Algoritmo quicksort. ...................................................................................................... 25 Análisis del algoritmo quicksort. ............................................................................... 25 Ordenación BinSort y RadixSort. ....................................................................................... 27 Método de Binsort. ............................................................................................................... 27 Algoritmo de ordenación Binsort. ............................................................................. 27 Método de Radixsort. ........................................................................................................... 28 Algoritmo de ordenación Radixsort. ......................................................................... 29 Bibliografía. ................................................................................................................................ 31 1
  3. 3. Búsqueda, Clasificación e Intercalación. Con mucha frecuencia los programadores trabajan con grandes cantidades de datos almacenados en arrays y registros, y por ello será necesario determinar si un array contiene un valor que coincida con un cierto valor clave. El proceso de encontrar un elemento específico de un array se denomina búsqueda. La operación de búsqueda nos permite encontrar datos que están previamente almacenados. La operación puede ser un éxito, si se localiza el elemento buscado o un fracaso en otros casos. La búsqueda se puede realizar sobre un conjunto de datos ordenados, lo cual hace la tarea más fácil y consume menos tiempo; o se puede realizar sobre elementos desordenados, tarea más laboriosa y de mayor insumo de tiempo. Búsqueda. Búsqueda Interna será aquella acción que se realice sobre datos que se encuentran en la memoria principal, por ejemplo en un arreglo. Búsqueda Externa es cuando todos sus elementos se encuentran en memoria secundaria (archivos almacenados en dispositivos de cinta, disco, etc.-) La operación de búsqueda de un elemento X en un conjunto consiste en determinar si el elemento X pertenece al conjunto y en este caso dar su posición, o bien, determinar que el elemento X no pertenece al conjunto. Los métodos más usuales para la búsqueda son: Búsqueda secuencial o lineal Búsqueda binaria Búsqueda por transformación de claves Búsqueda lineal o secuencial, la técnica más sencilla. La búsqueda secuencial es la técnica más simple para buscar en una lista de datos. Este método consiste en recorrer una lista o arreglo en forma secuencial y comparar cada elemento del arreglo con el valor deseado, hasta que éste se encuentre o finalice el arreglo. Normalmente cuando la función de búsqueda termina con éxito, es decir encontró el dato buscado, interesa conocer en qué posición fue encontrado el dato buscado. Esta idea se puede generalizar en todos los métodos de búsqueda. La búsqueda secuencial no requiere ningún requisito para el arreglo, y por lo tanto no necesita estar ordenado. 2
  4. 4. Ejemplo de algoritmo de búsqueda secuencial. Inicio Ingresar X Leer V(100) Desde I = 1 hasta 100 hacer Si V(i) = X entonces Imprimir “Encontrado” V(i), “Posición” i Fin Fin Si Fin desde Imprimir “Dato no encontrado” Fin 3
  5. 5. El método es solo adecuado para listas cortas de datos. A la hora de analizar la complejidad del método secuencial, tenemos que tener en cuenta el caso más favorable y el más desfavorable. Cuando el elemento no se encuentra tiene que realizar las n comparaciones. Y en los casos en que el elemento buscado se localiza, este podrá estar en el primer lugar, en el último o en un lugar intermedio. Entonces, al buscar un elemento en un arreglo de N componentes se harán: N comparaciones si el elemento no se localiza. N comparaciones si el elemento está en la última posición. 1 comparación si está en el primer lugar. i comparaciones si está en un lugar intermedio (posición 1 < i < N). Analizando lo escrito anteriormente podemos suponer que el número medio de comparaciones a realizar es de (n + 1) / 2 , que es aproximadamente igual a la mitad de los elementos de la lista. Una aplicación de la búsqueda puede ser en: Vector: Se recorre el vector de izquierda a derecha hasta encontrar una componente cuyo valor coincida con el buscado ó hasta que se acabe el vector. En este último caso el algoritmo debe indicar la no-existencia de dicho valor. Este método es válido para vectores ordenados o no, aunque para los vectores ordenados veremos otros métodos más eficientes. Vector Ordenado: Cuando el vector de búsqueda esta ordenado se consigue un algoritmo más eficiente, sin más que modificar la condición de fin del caso anterior. La ventaja que se obtiene es que una vez sobrepasado el valor buscado, no es necesario recorrer el resto del vector para saber que el valor no existe. Matriz: Se realiza mediante el anidamiento de dos bucles de búsqueda HASTA cuya finalización vendrá dada por la aparición del valor buscado o la terminación de la matriz. El recorrido se podrá hacer indistintamente por fila o por columna. Búsqueda de máximos y mínimos. En muchos casos, es necesario determinar el mayor o el menor valor de un conjunto de datos. Existen diversos algoritmos para esta determinación, en la mayoría de ellos se realizan comparaciones sucesivas de todos y cada uno de los datos resguardando en una variable auxiliar el valor que resulte mayor o menor, de acuerdo a lo que se busque, de manera tal que cuando no existan más datos para comparar, esta variable auxiliar contendrá el valor máximo o mínimo buscado. 4
  6. 6. Existen tres métodos para la resolución de este problema: Ramificación del árbol. Campeonato. Supuesto o prepo. Ramificación del árbol: Consiste en las combinaciones de comparaciones de todas las variables que intervienen. Este método se realiza teniendo en cuenta que todos los campos deben estar simultáneamente en memoria (es del tipo de búsqueda interna). Este método es al que tienden naturalmente todos los alumnos, en primera instancia, para la resolución del problema. Comenzar Mientras no EOF Leer A,B,C Si A>B Entonces Si A>C Entonces Imprimir “Mayor “A Si_no Si B>C Entonces Imprimir “Mayor “ B Si_no Imprimir “Mayor “C Fin_si Fin_si Si_no Si B>C Entonces Imprimir “Mayor “B Si_no Imprimir “Mayor “C Fin_si Fin_si Fin_mientras Parar 5
  7. 7. 6
  8. 8. Campeonato: Consiste en la comparación de a pares de todas las variables que intervienen. En este método los campos también deben estar simultáneamente en memoria. 7
  9. 9. Supuesto o Prepo: consiste en suponer que una de las variables que existen en memoria, en el mismo momento, es mayor o menor de todas, y luego se realiza las comparaciones sucesivas con las restantes. Este método se adapta para los algoritmos de búsqueda externa (los campos no están simultáneamente en memoria, sino que ingresan registro a registro). Búsqueda externa. Debemos tener en cuenta para el desarrollo del método con búsqueda externa lo siguiente: 1) El ingreso de la información: los datos ingresan de a uno en la memoria. 2) Se supone al primer dato como mayor (no cualquiera de los campos como en búsqueda interna) 3) Se realiza la comparación de una variable (nota promedio) con respecto a la variable auxiliar MAYOR, y se repite dicha comparación hasta el fin del lote de datos, formando de esta manera un CICLO DE BUSQUEDA. 8
  10. 10. Las mismas consideraciones son válidas para la búsqueda de MINIMOS. Una variante de este ejemplo es que la variable auxiliar tenga un valor inicial, que pueda darse de la siguiente manera: Para la determinación de máximos se colocará en la variable el menor valor que por la naturaleza de los datos pueda requerirse. Para la determinación del mínimo se colocará en la variable el mayor valor que esta pueda tomar, en función de la naturaleza de los datos. 9
  11. 11. En el último ejemplo se evita la doble lectura. El uso de estas técnicas, en búsquedas internas, es aconsejable cuando manejamos un número reducido de variables, con las salvedades y restricciones que en cada uno de los métodos ya mencionamos. En este caso se recomienda el uso de variables con subíndices o subindicadas. Búsqueda binaria o dicotómica, la técnica más eficiente. Es válido exclusivamente para datos ordenados y consiste en comparar en primer lugar con la componente central de la lista, y si no es igual al valor buscado se reduce el intervalo de búsqueda a la mitad derecha o izquierda según donde pueda encontrarse el valor a buscar. El algoritmo termina si se encuentra el valor buscado o si el tamaño del intervalo de búsqueda queda anulado. Este mecanismo es muy eficaz para buscar un elemento cualquiera que esté en una lista ordenada, y recibe el nombre de Búsqueda Binaria o Dicotómica cuya resolución se basa en el algoritmo de divisiones sucesivas en mitades. 10
  12. 12. Con cada iteración del método el espacio de búsqueda se reduce a la mitad, por lo tanto el número de comparaciones disminuye considerablemente en cada iteración. Esta disminución es más significativa cuanto mayor sea el número de elementos de la lista. En Pseudocódigo: Comenzar Leer X Ingresar V(I) I = 1,100 ULTIMO = 100 PRIMERO = 1 Hasta PRIMERO <= ULTIMO CENTRAL = [(PRIMERO + ULTIMO) / 2] Si V(CENTRAL) = X Entonces Imprimir “Registro encontrado “ V(CENTRAL) Parar Fin_si Si V(CENTRAL) > X Entonces ULTIMO = CENTRAL – 1 Si_no PRIMERO = CENTRAL + 1 Fin_si Fin_Hasta Imprimir “Registro no encontrado” Parar 11
  13. 13. Igual que en el método secuencial la complejidad del método se va a medir por los casos extremos que puedan presentarse en el proceso de búsqueda. El caso más favorable se dará cuando el primer elemento central es el buscado, en cuyo caso se hará una sola comparación. El caso más desfavorable se dará cuando el elemento buscado no está en las sublistas, en este caso se harán en forma aproximada log 2(n) comparaciones, ya que en cada ciclo de comparaciones el número de elementos se reduce a la mitad, factor de 2. Por lo tanto, el número medio de comparaciones que se realizarán con este método es de: (1 + log 2(n)) / 2 Si comparamos ambos métodos, resulta que para el mismo valor de N el método binario es más eficiente que el método secuencial; además la diferencia es más significativa cuanto más crece N. 12
  14. 14. Clasificación u Ordenación. Clasificar u ordenar significa reagrupar o reorganizar un conjunto de datos en una secuencia específica. El proceso de clasificación y búsqueda es una actividad muy frecuente en nuestras vidas. Vivimos en un mundo desarrollado, automatizado, donde la información representa un elemento de vital importancia. Los elementos ordenados aparecen por doquier. Registros de pacientes en un hospital, directorios telefónicos, índice de libros en una biblioteca, son tal solo algunos ejemplos de objetos ordenados con los cuales el ser humano se encuentra frecuentemente. La clasificación es una actividad fundamental. Imaginémonos un alumno que desea encontrar un libro en una biblioteca que tiene 100000 volúmenes y estos están desordenados o están registrados en los índices por orden de fecha de compra. También podemos pensar lo que ocurriría si deseamos encontrar el número de teléfono de una persona y la guía telefónica se encuentra ordenada por número. Sea A una lista de N elementos: A1, A2, A3, ........., An Clasificar significa permutar estos elementos de tal forma que los mismos queden de acuerdo con un orden preestablecido. Ascendente: A1 <= A2 <= A3 <= A4 ......<= An Descendente: A1 >= A2 >= A3 >= A4 ...... >=An En el procesamiento de datos, a los métodos de ordenación se les clasifica en dos categorías: Categoría de arreglos Categoría de archivos En cuanto a la cantidad de comparaciones que se realizan en un algoritmo se puede clasificar en: Directos de orden O (N2) Logarítmicos de orden O(N * log N) • • Los métodos directos tienen la característica de que su resolución es más corta, de fácil elaboración y comprensión, aunque son ineficientes cuando el número de elementos de un arreglo N, es mediano o considerablemente grande. Los métodos logarítmicos son más complejos con respecto a los directos, pero requieren menos comparaciones y movimientos para ordenar sus elementos, pero su elaboración y compresión resulta más sofisticada y abstracta. Se debe tener en cuenta que la eficiencia entre los distintos métodos se mide por el tiempo de ejecución del algoritmo y este depende fundamentalmente del número de comparaciones y movimientos que se realicen entre sus elementos. 13
  15. 15. Por lo tanto podemos decir que cuando N es pequeño debe utilizarse métodos directos y cuando N es mediana o grande deben emplearse métodos logarítmicos. Métodos Directos o Básicos: Ordenación por Intercambio Directo (Burbuja) Ordenación por Selección (Obtención sucesivas de menores) Ordenación por Inserción (Baraja) Métodos Logarítmicos o Avanzados: Método de Shell (Inserción con incrementos decrecientes) Método de QuickSort (Clasificación Rápida) Método de Binsort (Clasificación por mezcla) Método de Radixsort Ordenación por intercambio. Este método tiene dos versiones basadas en la misma idea que consiste en recorrer sucesivamente la lista o arreglo, comparando pares sucesivos de elementos adyacentes, permutando los pares desordenados. Se realizan (n-1) pasadas, transportando en cada pasada el menor o mayor elemento (según sea el caso) a su posición ideal. Al final de las (n-1) pasadas los elementos del arreglo estarán ordenados. El recorrido del vector se puede hacer de izquierda a derecha (desplazando los valores mayores hacia su derecha) o de derecha a izquierda (desplazando los valores menores hacia su izquierda), ambos para la clasificación en orden ascendente. El algoritmo de resolución deberá seguir los siguientes pasos: Comparar elemento (1) y elemento (2); si están ordenados, se deja como está; caso contrario se realiza el intercambio. Se comparan los dos elementos siguientes adyacentes elemento (2) y (3); y de nuevo se intercambia si es necesario. El proceso continúa hasta que cada elemento del arreglo haya sido comparado con sus elementos adyacentes y hayan sido intercambiados en los casos necesarios. La acción de intercambiar los elementos adyacentes requiere de una variable auxiliar. El proceso de esta triangulación será: AUX = A(I) A(I) = A(I+1) A(I+1) = AUX 14
  16. 16. 15
  17. 17. Luego de este análisis y en forma genérica podemos observar que si se efectúan n-1 pasadas y a su vez cada pasada requiere n-1 comparaciones, la ordenación total de una tabla exigirá (n-1) * (n-1) = (n-1)2 comparaciones de elementos. La cantidad de movimientos que se realicen en el arreglo dependerá del grado de desorden en que estén los datos. Otro aspecto a considerar es el tiempo necesario para la ejecución del algoritmo, el mismo es proporcional a n2. 16
  18. 18. Comenzar Ingresar N Ingresar A(I) I = 1,N Desde J = 1 hasta N –1 Desde I = 1 hasta N –1 Si A(I) > A(I+1) Entonces AUXI = A(I) A(I) = A(I+1) A(I+1) = AUXI Fin_si Fin_desde Fin_desde Parar Ordenación por selección. Este método consiste en buscar o seleccionar el elemento menor del arreglo y colocarlo en la primera posición, si el ordenamiento es ascendente. Luego se busca el segundo elemento más pequeño y se lo ubica en la segunda posición y así sucesivamente hasta llegar al último elemento. Por basarse este mecanismo en obtener los menores y ubicarlos en la posición ideal, recibe el nombre de obtención sucesiva de menores. Por ejemplo: Con este mecanismo, si pretendemos ordenar en forma creciente una tabla que posee 100 elementos, el método obliga a recorrer la tabla tantas veces como elementos tenga menos uno. En el primer recorrido se averigua cual es el elemento menor y se intercambia con el que esté en la primera posición de la tabla. En el segundo recorrido se averigua el menor entre los restantes elementos y se lo intercambia con el que está en la segunda posición. El resto de los recorridos utilizará la misma lógica. 17
  19. 19. 18
  20. 20. Si analizamos el desarrollo anterior podemos darnos cuenta que se realizan (n-1) recorridos, lo cual es un inconveniente del método dado que nos obliga a recorrer la lista un número fijo de veces, sin detectar si esta queda ordenada en alguno de los recorridos. Al igual que en el método por intercambio, el número de comparaciones entre elementos es independiente de la disposición inicial de los mismos. En el primer recorrido se realizan (n-1) comparaciones, en el segundo recorrido (n-2) comparaciones y así sucesivamente hasta llegar al último recorrido en la cual se realiza 1 comparación. Por lo tanto la cantidad total de comparaciones la expresamos de la siguiente manera: C = (n-1) + (n-2) + ...... + 2 + 1 = n * (n-1) / 2 Que es igual a: C = n2 – n / 2 En cuanto al número de movimientos será n-1 ya que el método, tal cual está desarrollado, realiza intercambio de un elemento consigo mismo. Comenzar Leer N Ingresar V(I) I = 1,N Desde I = 1 hasta N –1 MENOR = V(I) K=I Desde J = I + 1 hasta J = N Si V(J) < MENOR Entonces MENOR = V(J) K=J Fin_si Fin_desde V(K) = V(I) V(I) = MENOR Fin_desde Parar 19
  21. 21. 20
  22. 22. Ordenación por Inserción. El método de ordenación por inserción es similar al proceso típico de ordenar tarjetas de nombres (cartas de una baraja) por orden alfabético, que consiste en insertar un nombre en su posición correcta dentro de una lista o archivo que ya está ordenado. Así, por ejemplo, el proceso en el caso de la lista de enteros A = 50, 20, 40, 80, 30. Algoritmo de ordenación por inserción. El algoritmo correspondiente a la ordenación por inserción contempla los siguientes pasos: 1) El primer elemento A [0] se considera ordenado; es decir, la lista inicial consta de un elemento. 2) Se inserta A [1] en la posición correcta, delante o detrás de A[0], dependiendo de que sea menor o mayor. 3) Por cada bucle o iteración i (desde i=1 hasta n-1) se explora la sublista A [i-1] . . A [0] buscando la posición correcta de inserción; a la vez se mueve hacia abajo (a la derecha en la sublista) una posición todos los elementos mayores que el elemento a insertar A[i], para dejar vacía esa posición. 4) Insertar el elemento a la posición correcta. Ordenación Shell. La ordenación Shell debe el nombre a su inventor, D. L. Shell. Se suele denominar también ordenación por inserción con incrementos decrecientes. Se considera que el método Shell es una mejora de los métodos de inserción directa. En el algoritmo de inserción, cada elemento se compara con los elementos contiguos de su izquierda, uno tras otro. Si el elemento a insertar es el más pequeño hay que realizar muchas comparaciones antes de colocarlo en su lugar definitivo. El algoritmo de Shell modifica los saltos contiguos resultantes de las comparaciones por saltos de mayor tamaño y con ello se consigue que la ordenación sea más rápida. Generalmente se toma como salto inicial n/2 (siendo n el número de elementos), luego se reduce el salto a la mitad en cada repetición hasta que el salto es de tamaño 1. 21
  23. 23. Por ejemplo el caso de ordena una lista de elementos siguiendo paso a paso el método de Shell. Ejemplo. Obtener las secuencias parciales del vector al aplicar el método Shell para ordenar en orden creciente la lista: 6 1 5 2 3 4 0 El número de elementos que tiene la lista es 6, por lo que el salto inicial es 6/2 = 3. La siguiente tabla muestra el número de recorridos realizados en la lista con los saltos correspondiente. Algoritmo de ordenación Shell. Los pasos a seguir por el algoritmo para una lista de n elementos son: 1) Dividir la lista original en n/2 grupos de dos, considerando un incremento o salto entre los elementos de n/2. 2) Clarificar cada grupo por separado, comparando las parejas de elementos, y si no están ordenados, se intercambian. 3) Se divide ahora la lista en la mitad de grupos (n/4), con un incremento o salto entre los elementos también mitad (n/4), y nuevamente se clasifica cada grupo por separado. 4) Así sucesivamente, se sigue dividiendo la lista en la mitad de grupos que en el recorrido anterior con un incremento o salto decreciente en la mitad que el salto anterior, y luego clasificando cada grupo por separado. 5) El algoritmo termina cuando se consigue que el tamaño del salto sea 1. 22
  24. 24. Por consiguiente, los recorridos por la lista están condicionados por el bucle, intervalo n/2 mientras (intervalo > 0) hacer Para dividir la lista en grupos y clasificar cada grupo se anida este código, desde i (intervalo + 1) hasta n hacer i - intervalo j mientras (j > 0) hacer k j + intervalo si (a[j] <= a[k]) entonces j −1 sino Intercambio (a[j], a[k]); j j - intervalo fin_si fin_mientras fin_desde En el código anterior se observa que se comparan pares de elementos indexados por j y k, (a[j],a[k]) , separados por un salto, intervalo . Así, si n = 8 el primer valor de intervalo = 4, y los índices i = 5, j = 1, k = 6. Los siguientes valores de los índices son i = 6, j = 2, k = 7,y así hasta recorrer la lista. Para realizar un nuevo recorrido de la lista con la mitad de grupos, el intervalo se hace la mitad: intervalo intervalo / 2 así se repiten los recorridos por la lista, mientras intervalo > 0. Ordenación Rápida (Quicksort). El algoritmo conocido como quicksort (ordenación rápida) recibe el nombre de su autor, Tony Hoare. La idea del algoritmo es simple, se basa en la división en particiones de la lista a ordenar, por lo que se puede considerar que aplica la técnica divide y vencerás. El método es, posiblemente, el más pequeño de código, más rápido, más elegante, más interesante y eficiente de los algoritmos de ordenación conocidos. El método se basa en dividir los n elementos de la lista a ordenar en dos partes o particiones separadas por un elemento: una partición izquierda, un elemento central denominado pivote o elemento de partición, y una partición derecha. La partición o división se hace de tal forma que todos los elementos de la primera sublista (partición izquierda) son menores que todos los elementos de la segunda sublista (partición derecha). Las dos sublistas se ordenan entonces independientemente. Para dividir la lista en particiones (sublistas) se elige uno de los elementos de la lista y se utiliza como pivote o elemento de partición. Si se elige una lista cualquiera con los elementos en orden aleatorio, se puede seleccionar cualquier elemento de la lista como pivote, por ejemplo, el primer elemento de la lista. Si la lista tiene algún orden 23
  25. 25. parcial conocido, se puede tomar otra decisión para el pivote. Idealmente, el pivote se debe elegir de modo que se divida la lista exactamente por la mitad, de acuerdo al tamaño relativo de las claves. Por ejemplo, si se tiene una lista de enteros de 1 a 10, 5 o 6 serían pivotes ideales, mientras que 1 o 10 serían elecciones «pobres» de pivotes. Una vez que el pivote ha sido elegido, se utiliza para ordenar el resto de la lista en dos sublistas: una tiene todas las claves menores que el pivote y la otra, todos los elementos (claves) mayores que o iguales que el pivote (o al revés). Estas dos listas parciales se ordenan recursivamente utilizando el mismo algoritmo; es decir, se llama sucesivamente al propio algoritmo quicksort. La lista final ordenada se consigue concatenando la primera sublista, el pivote y la segunda lista, en ese orden, en una única lista. La primera etapa de quicksort es la división o «particionado» recursivo de la lista hasta que todas las sublistas constan de sólo un elemento. Por Ejemplo. Se ordena una lista de números enteros aplicando el algoritmo quicksort, como pivote se elige el primer elemento de la lista.. 24
  26. 26. Algoritmo quicksort. La primera etapa en el algoritmo de partición es obtener el elemento pivote; una vez que se ha seleccionado se ha de buscar el sistema para situar en la sublista izquierda todos los elementos menores que el pivote y en la sublista derecha todos los elementos mayores que el pivote. Supongamos que todos los elementos de la lista son distintos, aunque será preciso tener en cuenta los casos en que existan elementos idénticos. Los pasos que sigue el algoritmo quicksort: Seleccionar el elemento central de a [0:n-1] como pivote. Dividir los elementos restantes en particiones izquierda y derecha, de modo que ningún elemento de la izquierda tenga una clave (valor) mayor que el pivote y que ningún elemento a la derecha tenga una clave más pequeña que la del pivote. Ordenar la partición izquierda utilizando quicksort recursivamente. Ordenar la partición derecha utilizando quicksort recursivamente. La solución es partición izquierda seguida por el pivote y a continuación partición derecha. Análisis del algoritmo quicksort. El análisis general de la eficiencia de quicksort es difícil. La mejor forma de ilustrar y calcular la complejidad del algoritmo es considerar el número de comparaciones realizadas teniendo en cuenta circunstancias ideales. Supongamos que n (número de elementos de la lista) es una potencia de 2,n = 2k (k = log2 n). Además, supongamos que el pivote es el elemento central de cada lista, de modo que quicksort divide la sublista en dos sublistas aproximadamente iguales. En la primera exploración o recorrido hay n − 1 comparaciones. El resultado de la etapa crea dos sublistas aproximadamente de tamaño n/2. En la siguiente fase, el proceso de cada sublista requiere aproximadamente n/2 comparaciones. Las comparaciones totales de esta fase son 2(n/2) = n. La siguiente fase procesa cuatro sublistas que requieren un total de 4(n/4) comparaciones, etc. Eventualmente, el proceso de división termina después de k pasadas cuando la sublista resultante tenga tamaño 1. El número total de comparaciones es aproximadamente: n + 2(n/2) + 4(n/4) + … + n(n/n) = n + n + … + n = n · k = n · log2 n Para una lista normal la complejidad de quicksort es O(n log2 n). El caso ideal que se ha examinado se realiza realmente cuando la lista (el array) está ordenado en orden ascendente. En este caso el pivote es precisamente el centro de cada sublista. 25
  27. 27. Si el array está en orden ascendente, el primer recorrido encuentra el pivote en el centro de la lista e intercambia cada elemento en las sublistas inferiores y superiores. La lista resultante está casi ordenada y el algoritmo tiene la complejidad O(n log2 n). El escenario del caso peor de quicksort ocurre cuando el pivote cae consistentemente en una sublista de un elemento y deja el resto de los elementos en la segunda sublista. Esto sucede cuando el pivote es siempre el elemento más pequeño de su sublista. En el recorrido inicial, hay n comparaciones y la sublista grande contiene n − 1 elementos. En el siguiente recorrido, la sublista mayor requiere n − 1 comparaciones y produce una sublista de n − 2 elementos, etc. El número total de comparaciones es: n + n − 1 + n − 2 + …+ 2 = (n − 1)(n + 2)/2 La complejidad es O(n2). En general el algoritmo de ordenación tiene como complejidad media O(n log2 n) siendo posiblemente el algoritmo más rápido. La siguiente tabla muestra las complejidades de los algoritmos empleados en los métodos explicados en el libro. Comparación de complejidad en métodos de ordenación En conclusión, se suele recomendar que para listas pequeñas los métodos más eficientes, inserción y selección; y para listas grandes, el quicksort. El algoritmo de Shell suele variar mucho su eficiencia en función de la variación del número de elementos por lo que es más difícil que en los otros métodos proporcionar un consejo eficiente. 26
  28. 28. Ordenación BinSort y RadixSort. Estos métodos de ordenación utilizan urnas para depositar en ellas los registros en el proceso de ordenación. En cada recorrido de la lista se depositan en una urna aquellos registros cuya clave tienen una cierta correspondencia con i. Método de Binsort. Este método, también llamado clasificación por urnas, persigue conseguir funciones de tiempo de ejecución menores de O(n log n), para ordenar una secuencia de n elementos siempre que se conozca algo acerca del tipo de las claves por las que se están ordenando. Supóngase que se tiene un vector v [] de registros, se quiere ordenar respecto campo clave de tipo entero, además se sabe que los valores de las claves encuentran en el rango de 1 a n, sin claves duplicadas y siendo n el número elementos. En estas circunstancias es posible colocar los registros ordenados en array auxiliar t [] mediante este bucle: un se de un for 1:= 1 to n do t[v[i].clave] = v[i]; Sencillamente determina la posición que le corresponde según el valor del campo clave. El bucle lleva un tiempo de ejecución de complejidad O(n). Esta ordenación tan sencilla que se ha expuesto es un caso particular del método de ordenación por urnas (binsort). Este método utiliza urnas, cada urna contiene todos los registros con una misma clave. El proceso consiste en examinar cada registro r a clasificar y situarle en la urna i, coincidiendo i con el valor del campo clave de r. En la mayoría de los casos en que se utilice el algoritmo, será necesario guardar más de un registro en una misma urna por tener claves repetidas. Entonces estas urnas hay que concatenarlas en el orden de menor índice de urna a mayor, así quedará el array en orden creciente respecto al campo clave. Algoritmo de ordenación Binsort. Se considera que el campo clave de los registros que se van a ordenar son números enteros en el rango 1 .. m. Son necesarias m urnas por lo que es necesario definir un vector de m urnas. Las urnas pueden ser representadas por listas enlazadas, cada elemento de la lista contiene un registro cuyo campo clave es el correspondiente al de la urna en la que se encuentra. Así en la urna 1 se sitúan los registros cuyo campo clave sea igual a 1, en la urna 2 los registros cuyo campo clave sea 2, y así sucesivamente en la urna i se sitúan los registros cuyo campo clave sea igual a i. Una vez que se hayan distribuido los registros en las diversas urnas es necesario concatenar las listas. En la siguiente figura se muestra cómo realizar la concatenación. 27
  29. 29. Concatenación de urnas representadas por listas enlazadas. Método de Radixsort. Este método puede considerarse como una generalización de la clasificación por urnas. Aprovecha la estrategia de la forma más antigua de clasificación manual, consistente en hacer diversos montones de fichas, cada uno caracterizado por tener sus componentes un mismo dígito (letra, si es alfabética) en la misma posición; estos montones se recogen en orden ascendente y se reparte de nuevo en montones según el siguiente dígito de la clave. Como ejemplo, suponer que se han de ordenar estas fichas identificadas por tres dígitos: Atendiendo al dígito de menor peso (unidades) las fichas se distribuyen en montones del 0 al 9; Recogiendo los montones en orden, la secuencia de fichas queda: 28
  30. 30. De esta secuencia podemos decir que está ordenada respecto al dígito de menor peso, respecto a las unidades. Pues bien, ahora de nuevo se distribuye la secuencia de fichas en montones respecto al segundo dígito: Recogiendo de nuevo los montones en orden, la secuencia de fichas queda: En este momento esta secuencia de fichas ya están ordenadas respecto a los dos últimos dígitos, es decir, respecto a las decenas. Por último, se distribuye las fichas en montones respecto al tercer dígito: Recogiendo de nuevo los montones en orden, la secuencia de fichas queda ya ordenada: 194, 216, 236, 247, 345, 365, 389, 425, 431, 467, 529, 572, 672, 721, 746, 834, 836, 891 Algoritmo de ordenación Radixsort. La idea clave de la ordenación Radixsort (también llamada por residuos) es clasificar por urnas primero respecto al dígito de menor peso (menos significativo) dk, después concatenar las urnas, clasificar de nuevo respecto al siguiente dígito dk −1, y así sucesivamente se sigue con el siguiente dígito hasta alcanzar el dígito más significativo dl, en ese momento la secuencia estará ordenada. La concatenación de las urnas consiste en enlazar el final de una con el frente de la siguiente. Al igual que en el método de Binsort, las urnas se representan mediante un vector de listas. En el caso de que la clave respecto a la que se ordena sea un entero, se tendrán 10 urnas, numeradas de 0 a 9. Si la clave respecto a la que se ordena es alfabética, habrá tantas urnas como letras distintas, desde la urna que represente a la letra a hasta la z. Para el caso de que clave sea entera, en primer lugar se determina el máximo número de dígitos que puede tener la clave. En un bucle de tantas iteraciones como máximo de dígitos se realizan las acciones de distribuir por urnas los registros, concatenar. 29
  31. 31. La distribución por urnas exige obtener el dígito del campo clave que se encuentra en la posición definida por el bucle externo, dicho dígito será el índice de la urna. 30
  32. 32. Bibliografía. • • • Material proporcionado por el espacio Curricular, “Algoritmos y Programación”, Profesorado en Informática, Instituto Superior de Formación Docente “Dr. Juan Pujol. 2013 Apuntes de la cátedra “Algoritmos y Estructuras de Datos II”, Licenciatura en Sistemas de Información, Facultad de Ciencias Exactas, Naturales y Agrimensura, UNNE. 2013 Departamento de Informática Universidad de Valladolid Campus de Segovia. 31

×