Mais conteúdo relacionado Semelhante a Ordenamiento parte 3 (20) Mais de Luis Fernando Aguas Bucheli (20) Ordenamiento parte 32. Usando los ordenamientos de Java
• Los API de Java proveen una clase Arrays con varios
métodos para diferentes tipos de arreglos.
• Las clases Collections proveen similares métodos de
ordenamiento.
• Los métodos de ordenamiento para arreglos de datos
primitivos se basan en quicksort
• Los métodos de ordenamiento para arreglos de objetos
y listas se basan en mergesort
2012 Octubre © Luis F. Aguas 2
3. Burbuja (Bubble)
• Este método realiza comparaciones de todas las posibles
parejas de llaves intercambiando aquellas que se
encuentran fuera de orden.
• Utiliza un proceso repetitivo comparando las parejas de
datos adyacentes del inicio al final del arreglo donde,
después de la primer pasada la llave mayor queda en la
última posición del arreglo.
4. Burbuja (Bubble)
Variables
•
•
n es el total de elementos
K arreglo de llaves
Burbuja
•
•
t variable auxiliar para el intercambio
i,j variables para los indices
Inicio
para i= n-1 ; i>0 ; i--
0 1 2 3 4 5
para j=0; i>j; j++
3 8 2 1 4 2
K si (k[j] > k[j+1])
Primera
pasada t = k[j];
3 8 2 1 4 2
k[j]= k[j+1];
3 2 8 1 4 2 k[j+1] = t;
Fin
3 2 1 8 4 2
3 2 1 4 8 2
3 2 1 4 2 8
5. 3 2 1 4 2 8
2 1 3 2 4 8
2 3 1 4 2 8 Tercer
Segunda pasada 1 2 3 2 4 8
pasada
2 1 3 4 2 8
1 2 3 2 4 8
2 1 3 4 2 8
1 2 2 3 4 8
2 1 3 2 4 8
1 2 2 3 4 8 Quinta
Cuarta 1 2 2 3 4 8
pasada pasada
1 2 2 3 4 8
1 2 2 3 4 8
1 2 2 3 4 8
6. Método de Burbuja 2/2
• Algoritmo
• Varias recorridos por el arreglo
• Se comparan pares sucesivos de elementos
• Si el orden es incremental (o idéntico), no hay cambio
• Si el orden es decremental, los elementos se intercambian
• Repetir
• Fácil de programar, pero ejecuta con lentitud
2012 Octubre © Luis F. Aguas 6
7. Análisis de método de burbuja 3/3
• Provee un excelente rendimiento en algunos casos y
muy pobre en otros.
• Trabaja mejor cuando el arreglo es ordenado
inicialmente.
• En el peor de los casos el numero de comparaciones
O(n2)
• En el peor de los casos los intercambios son O(n2)
• El mejor caso ocurre cuando el arreglo esta ordenado
• O(n) comparaciones
• O(1) intercambios
2012 Octubre © Luis F. Aguas 7
8. Comparación de métodos cuadráticos
• Ninguno de los algoritmos son buenos para arreglos
grandes.
2012 Octubre © Luis F. Aguas 8
9. 1. Aplicaciones de ordenamiento
2. Métodos cuadráticos
• Selección
• Burbuja
• Inserción
3. Métodos no cuadráticos
• Shellsort
• Mergesort
• Heapsort
• Quicksort
4. Comparación de métodos
2012 Octubre © Luis F. Aguas 9
10. Shellsort: Una mejor Inserción
• Shellsort es un tipo de inserción pero con O(n3/2) o
mejor rendimiento
• Descubierto por Donald Shell en 1959
• Aprovecha divide y conquista para insertar
• Antes de ordenar todo el arreglo, ordena muchos
pequeños sub-arreglos usando inserción antes de
ordenarlo completamente.
2012 Octubre © Luis F. Aguas 10
11. Shell sort
• El método shell divide el arreglo a ordenar en
varios grupos haciendo comparaciones e
intercambios entre ellos. El tamaño de los
subgrupos se decrementa y el número de
subgrupos se incrementa hasta llegar a tener n
grupos de tamaño 1. A partir de este punto, el
método funciona como el de inserción directa.
• El tamaño de los subgrupos así como el total de
estos puede determinarlos el usuario para
hacer mas eficiente el algoritmo.
12. Shellsort Características
• Compara los elementos que están muy aparte, entonces
acerca los elementos, etc. así elimina mucho movimiento
de datos.
• Incrementa la secuencia h1 = 1, h2, … hl
• Después de una fase j para todos los k A[k] ≤ A[k + hj] – la
entrada esta hj ordenada
• hj arreglo ordenado permanece hj arreglado después hj - 1
ordenamiento.
2012 Octubre © Luis F. Aguas 12
13. Shellsort
Shell sort Inicio
grupo = [ 21, 7, 3, 1]
Variables para g=0; g<4; g++
• K arreglo de datos a ordenar
• H tamaño del grupo h=grupo[g];
• i, j índices para el arreglo
• V variable auxiliar para i=h; i<n; i++
• N número de elementos
• grupo arreglo con los tamaños de grupo
v=k[i];
j=i;
379051 6 842061 5 734982 mientras (j>=h && a[j-h]>v)
k[j]=k[j-h];
3790516 8420615 734982 j=j-h;
k[j]=v;
3320515 7440616 879982 Fin
332 051 574 406 168 799 82
001 122 334 456 5 68 779 89
00112233445656877989
00112233445566778899
15. Shellsort Implementación
• Cada hj clasificación es llamada un gap así clasificamos
elementos hj aparte. Gap = = 1 resulta un inserción.
• Secuencia de incremento Hibbard
• Empieza el gap en N / 2, calcula el próximo gap
dividiendo en número anterior por 2
• Si el próximo gap es impar añade uno para hacerlo par
• El peor caso corre en O(N3 / 2)
• Una secuencia empírica – inicia el gap en N / 2, divide por
2.2 – tiempo promedio ejecución ≤ O(N5 / 4)
• ShellSort.java
2012 Octubre © Luis F. Aguas 15
17. MergeSort
• Un merge es un proceso común de datos que es
realizado con dos secuencias de datos con las
siguientes características
• Ambas secuencias contienen ítems con un método
común de comparación
• Los objetos e ambas secuencias son ordenadas de
acuerdo al método de comparación
2012 Octubre © Luis F. Aguas 17
18. MergeSort Algoritmo
1. Accese al primer ítem de ambas secuencias
2. Mientras no finalice cualquier secuencia
• Compare el ítem actual de las dos secuencias, copie el
ítem actual pequeño a la secuencia de salida, y accese al
próximo ítem de la secuencia de entrada donde los ítems
fueron copiados.
3. Copie cualquier ítem remanente de la primera
secuencia a la secuencia de salida.
4. Copie cualquier ítem remanente de la segunda
secuencia a la secuencia de salida
2012 Octubre © Luis F. Aguas 18
19. MergeSort
1. Divida el arreglo en dos equivalentes
5 1 3 2 4 7 6
2. Ordene (recursivamente) cada mitad usando Mergesort.
1 3 5 2 4 6 7
3. Mezcle (merge) las dos partes generadas
1 3 5
1 2 3
2 4 6 7
Los pequeños están al inicio
2012 Octubre © Luis F. Aguas 19
20. Mergesort (implementación)
public void mergesort ( double arr [ ],
int from, int to )
{
if (from <= to)
return;
int middle = (from + to ) / 2; Opcional si no esta
mergesort (arr, from, middle); ordenado
mergesort (arr, middle + 1, to);
if (arr [middle] > arr [middle+ 1] )
{
copy (arr, from, to, temp) ; double temp[ ] es
merge (temp, from, middle, to, arr); inicializado fuera
} del MergeSort
}
2012 Octubre © Luis F. Aguas 20
21. Análisis de MergeSort
• Para dos secuencias de entrada que contienen un total
de n elementos, necesitamos mover cada elemento de
entrada a la secuencia de salida.
• El tiempo del Merge es O(n)
• Necesitamos almacenar las dos secuencias iniciales y la
secuencia de salida.
• El arreglo no puede ser mezclado (merged) en el
lugar.
• Espacio adicional usado es O(n)
2012 Octubre © Luis F. Aguas 21
22. Análisis de MergeSort
• El número de operaciones de partición es O(log n)
• El numero de operaciones merge es O(n)
• El numero total de operaciones es O(n log n)
• Por hacer una copia recursiva de las variables locales
almacenadas en una pila en tiempo de ejecución. ASí
MergeSort requiere un almacenamiento adicional de
tamaño n.
2012 Octubre © Luis F. Aguas 22
23. Radix
• Radix Sort (ordenamiento Radix) es un algoritmo de
ordenamiento estable* para ordenar elementos
identificados por llaves (o claves) únicas. Cada llave
debe ser una cadena o un número capaz de ser
ordenada alfanuméricamente.
• Este método ejecuta un número de repeticiones igual al
número de caracteres de las llaves a ordenar. El Radix
Directo, inicia con el dígito más a la derecha repartiendo
los datos en “canastas”, estos datos se reparten de
nuevo de acuerdo al siguiente dígito y así
sucesivamente hasta terminar con el dígito de mas a la
izquierda.
24. 329 248 123 423 226 825 132 335 231 432 256 218
231 132 123 825 226 248 329
Distribución y
reacomodo
432 423 335 256 218
Digito
derecho
231 132 432 123 423 825 335 226 256 248 218 329
218 123 231 248 256
423 132
Distribución y
reacomodo 825 432
Digito
central
226 335
329
218 123 423 825 226 329 231 132 432 335 248 256
25. 218 123 423 825 226 329 231 132 432 335 248 256
123 218 329 423 825
132 226 335 432
Distribución y 231
reacomodo
Digito
izquierdo 248
256
123 132 218 226 231 248 256 329 335 423 432 825
27. Algoritmo HeapSort
• Este algoritmo de ordenación está basado en la
estructura de montículo.
• Se define montículo de tamaño n como un árbol binario
completo de n nodos, tal que el contenido de cada nodo
es mayor o igual al contenido de su parte.
2012 Octubre © Luis F. Aguas 27
28. Heapsort - I
• El tiempo del merge es O(nlogn) pero requiere
temporalmente, n almacenamiento extra para los ítems
• Heapsort no requiere ningún almacenamiento adicional
• Algoritmo:
1. Inserte cada valor del arreglo en el montículo (heap)
(cola prioridad)
2. Inicie el index a 0
3. Mientras el heap no este vacío
4. Remueva un ítem (elemento del tope) desde el heap
e insértelo en la posición index en el arreglo
5. Incremente index
2012 Octubre © Luis F. Aguas 28
29. Heapsort - II
• El algoritmo es O(n log n) pero requiere, temporalmente,
n almacenamiento extra
2012 Octubre © Luis F. Aguas 29
30. Algoritmo para Heapsort en lugar - I
1. Construir un heap para rearreglar los elementos en un
arreglo no ordenado (reusamos el arreglo)
2. Mientras el heap no está vacío
• Remover el primer ítem del heap intercambiándolo
con el último ítem y restaurando la propiedad heap
2012 Octubre © Luis F. Aguas 30
31. Algoritmo para Heapsort en lugar - II
• Construir un heap para rearreglar los elementos en un
arreglo no ordenado (reusamos el arreglo)
1. Poner index a 0
2. Mientras el index es menor que array.length
• Incremente index en 1 == Insertar el próximo
elemento en el heap
• Restaurar la propiedad heap para los elementos en
posiciones 0 hasta index (incrementando el paso
previo)
2012 Octubre © Luis F. Aguas 31
32. Análisis de HeapSort
• HeapSort.java
• Construir el heap es O(log n)
• El número de operaciones insert es O(n)
• El numero total de operaciones es O(n log n)
• Reusamos el arreglo original así no se necesita
almacenamiento adicional
2012 Octubre © Luis F. Aguas 32
33. Quicksort
• Desarrollado en 1962 por C. A. R. Hoare
• Recursivo
• Divide y conquista
• Quicksort rearregla un arreglo en dos partes así todos
los elementos en el arreglo izquierdo son menores o
iguales que un valor específico llamado pivote
• Quicksort asegura que los elementos en el arreglo
derecho sean mayores que el pivote
• El caso promedio para Quicksort es O(n log n)
2012 Octubre © Luis F. Aguas 33
34. Quicksort Algoritmo
Sea S el número de elementos a clasificar
1. Si el numero de elementos en S es 0 o 1 pare y vuelva al
caso base
2. Tome un elemento v desde S llamado pivote
3. Divida los elementos restantes (S - {v}) en dos conjuntos
disjuntos:
L = {x IN (S - {v}) Y x ≤ v}
R = {x IN (S - {v}) Y x ≥ v}
4. Regrese el resultado de aplicar quicksort a L seguido por v
y continúe por el resultado aplicando quicksort a R
2012 Octubre © Luis F. Aguas 34
37. Quicksort Ejemplo - I
Arreglo Original
Pivote 6 es ubicado al final
i para en el elemento 8; j para en el elemento
menor 2
2012 Octubre © Luis F. Aguas 37
38. Quicksort Ejemplo - II
Los elementos 8 y 2 desordenados son
cambiados
i se detiene en 9; j detiene en el elemento
pequeño 5
Los elementos 9 y 5 se intercambian
2012 Octubre © Luis F. Aguas 38
39. Quicksort Ejemplo – III
i para en 9; j para en el 3
Intercambia pivote y elemento en posición i
2012 Octubre © Luis F. Aguas 39
40. Algoritmo en Pseudocódigo
• Inicialización de variables
pivote = lista[sup];
i = inf - 1;
j = sup; 4. cont = 1;
// Verificamos que no se crucen los límites
if (inf >= sup)
retornar;
// Clasificamos la sublista
while (cont)
while (lista[++i] < pivote);
while (lista[--j] > pivote);
if (i < j)
temp = lista[i];
lista[i] = lista[j];
lista[j] = temp;
else
cont = 0;
2012 Octubre © Luis F. Aguas 40
41. Algoritmo en Pseudocódigo
// Copiamos el pivote en su posición final
temp = lista[i];
lista[i] = lista[sup];
lista[sup] = temp;
// Aplicamos el procedimiento recursivamente a cada sublista
QuickSort (lista, inf, i - 1);
QuickSort (lista, i + 1, sup);
2012 Octubre © Luis F. Aguas 41
42. Seleccionando el Pivote
• Quicksort es O(n*n) cuando cada partición contiene un
arreglo vacío, que es el caso cuando el arreglo es pre-
ordenado.
• La mejor solución es tomar el valor del pivote de manera
que sea lo menor para una mala partición.
• Primer elemento – una mala selección
• En general, no seleccione el pivote cerca del inicio o del
final del conjunto.
• Un elemento intermedio es una buena opción
• Medio de tres – la media del primer, intermedio y último
elemento.
2012 Octubre © Luis F. Aguas 42
43. Pivote Media-de-tres Ejemplo - I
Arreglo Original
Resultado del ordenamiento de tres elementos
(primero, medio, y último)
2012 Octubre © Luis F. Aguas 43
45. Descripción
• Se elige un pivote.
• Se reubican los elementos respecto al pivote los
menores antes, los mayores atrás.
• El arreglo queda separado en dos subarreglos
• Se repite el proceso con los subarreglos resultantes
• El arreglo esta ordenado
46. Ejecución por pasos
• 4-8-1-7-2-3-5
• 4-8-1-7-2-3-5
• 4-8-1-7-2-3-5
• 3-8-1-7-2-4-5
• 3-8-1-7-2-4-5
• 3-4-1-7-2-8-5
• 3-4-1-7-2-8-5
• 3-4-1-2-7-8-5
• 3-4-1-2-5-8-7
• 3-4-1-2
• 1-4-3-2
• 1-2-3-4
• 8-7
• 7-8
• 1-2-3-4-5-7-8
47. •
•
•
import java.util.Comparator;
import java.util.Random;
public class Quicksort {
Implementación
•
•
•
public static final Random RND = new Random();
private void swap(Object[] array, int i, int j) {
Object tmp = array[i];
en Java
• array[i] = array[j];
• array[j] = tmp;
• }
• private int partition(Object[] array, int begin, int end, Comparator cmp) {
• int index = begin + RND.nextInt(end - begin + 1);
• Object pivot = array[index];
• swap(array, index, end);
• for (int i = index = begin; i < end; ++ i) {
• if (cmp.compare(array[i], pivot) <= 0) {
• swap(array, index++, i);
• }
• }
• swap(array, index, end);
• return (index);
• }
• private void qsort(Object[] array, int begin, int end, Comparator cmp){
• if (end > begin) {
• int index = partition(array, begin, end, cmp);
• qsort(array, begin, index - 1, cmp);
• qsort(array, index + 1, end, cmp);
• }
• }
• public void sort(Object[] array, Comparator cmp){
• qsort(array, 0, array.length - 1, cmp);
• }
• }