4 - Dsic
Transcripción
4 - Dsic
EDA. Tema 8 Colas de Prioridad: Heaps Natividad Prieto Sáez. DSIC EDA, T-8. Curso 02/03. N.Prieto– p.1/55 Objetivos Estudio de las definiciones asociadas a las Colas de Prioridad: Especificación: operaciones que las caracterizan como estructuras de datos. Construcción y uso de su interfaz Java: ColaPrioridad. Immplementación usando heaps: clase MonticuloBinario. Diseño e implementación del método de ordenación heapSort EDA, T-8. Curso 02/03. N.Prieto– p.2/55 Bibliografía M.A. Weiss. Estructuras de Datos en Java. Ed. Addison Wesley, 2000.Capítulo 6, apartado 8 y capítulo 20, apartados del 1 al 5. R. Wiener, L.J. Pinson. Fundamental of OOP and Data Structures in Java. Cambridge University Press, 2000. Capítulo 12, apartados 2 y 3. EDA, T-8. Curso 02/03. N.Prieto– p.3/55 Índice 1. Introducción Colas de Prioridad Implementaciones básicas y costes EDA, T-8. Curso 02/03. N.Prieto– p.4/55 Índice 1. 2. Introducción La interfaz ColaPrioridad EDA, T-8. Curso 02/03. N.Prieto– p.4/55 Índice 1. 2. 3. Introducción La interfaz ColaPrioridad Los Heaps (Montículos) Definición y propiedades Implementación sobre vector EDA, T-8. Curso 02/03. N.Prieto– p.4/55 Índice 1. 2. 3. Introducción La interfaz ColaPrioridad Los Heaps (Montículos) 4. Implementación de Cola de Prioridad utilizando un Heap La operación para insertar La operación eliminarMin EDA, T-8. Curso 02/03. N.Prieto– p.4/55 Índice 1. 2. 3. Introducción La interfaz ColaPrioridad Los Heaps (Montículos) 4. Implementación de Cola de Prioridad utilizando un Heap 5. El método de ordenación HeapSort EDA, T-8. Curso 02/03. N.Prieto– p.4/55 Introducción Una cola de prioridad es una ED para representar conjuntos con las operaciones: Acceder al elemento menor de la colección y eliminar este elemento Permiten modelizar: la gestión de un planificador de tareas en un SMU los trabajos que consumen menos recursos 1o los trabajos del administrador del sistema 1o la gestión de los trabajos enviados a impresión los trabajos más importantes primero los trabajos más cortos primero Para ello, a cada item se le asocia un valor numérico para medir su prioridad: valores menores implican importancias mayores EDA, T-8. Curso 02/03. N.Prieto– p.5/55 Implementación de Colas de Prioridad ¿Qué estructuras de datos podríamos usar para implementar una cola de prioridad? E. Datos Lista Lista Ord ABB Heaps buscarMin O(N) O(1) O(log N) O(1) eliminarMin O(N) O(1) O(log N) O(log N) insertar O(1) O(N) O(log N) O(log N) EDA, T-8. Curso 02/03. N.Prieto– p.6/55 La interfaz ColaPrioridad import Excepciones.*; public interface ColaPrioridad { void insertar (Comparable x); Comparable buscarMin () throws DesbordamientoInferior; // devuelve el elemento menor Comparable eliminarMin () throws DesbordamientoInferior; // devuelve y elimina el elemento menor void vaciar (); boolean esVacia (); } EDA, T-8. Curso 02/03. N.Prieto– p.7/55 Heaps 1. Propiedad estructural: Un Árbol Binario es Completo si tiene todos sus niveles completos, a excepción quizás del último, en el cuál todas las hojas están situadas tan a la izquierda como sea posible Propiedades: Su altura es a lo sumo (log N) Admite una representación implícita sobre vector 2. Propiedad de orden: El valor de cualquier nodo es menor o igual que el de sus hijos (Min-Heap) De manera análoga se define un Max-heap EDA, T-8. Curso 02/03. N.Prieto– p.8/55 Propiedades Un heap es un AB completo con la propiedad de orden enunciada Propiedades: Todas las ramas del árbol son secuencias ordenadas La raíz del árbol es el nodo de valor mínimo (o máximo en un Max-Heap) Todo subárbol de un Heap es también un Heap Cuestiones: ¿Cuál es la diferencia entre las propiedades de orden en los ABB y en los Heaps? ¿Puede utilizarse la propiedad de orden en un Heap para listar de forma ordenada las claves del conjunto en tiempo lineal? EDA, T-8. Curso 02/03. N.Prieto– p.9/55 Implementación de Heaps Representación implícita Vector de objetos, v Entero que representa el tamaño del heap, n v[1] es la raíz, mínimo en un Min-Heap (o máximo en un Max-Heap) Dado un nodo v[i], Si 2i ≤ n, v[2i] es el nodo hijo izquierdo Si 2i + 1 ≤ n, v[2i+1] es el nodo hijo derecho Si i 6= 1, v[i/2] es el nodo padre Propiedad de orden: (0) ∀i : 1 < i ≤ n : v[i/2] ≥ v[i] EDA, T-8. Curso 02/03. N.Prieto– p.10/55 Operaciones básicas insertar: para añadir un elemento al conjunto. Coste O(log N) eliminarMin: para devolver y eliminar el elemento menor del conjunto. Coste O(log N) construirHeap: para convertir un vector en principio desordenado, en un heap. Coste O(N) heapSort: para ordenar un vector. Coste O(N log N) EDA, T-8. Curso 02/03. N.Prieto– p.11/55 Atributos de la clase MonticuloBinario private Comparable [] vector; // El vector del heap private int tamActual; // Número de elementos d private static final int CAPACIDAD= 11; EDA, T-8. Curso 02/03. N.Prieto– p.12/55 La operación constructora public MonticuloBinario(Comparable infNeg) { //usa la posición 0 como centinela vector[0]=-infinito tamActual=0; obtenerVector(CAPACIDAD); vector[0]=infNeg; } private void obtenerVector (int nuevoTam) { // incluye una posici’on extra para el centinela vector=new Comparable[nuevoTam+1]; } EDA, T-8. Curso 02/03. N.Prieto– p.13/55 La operación insertar Añadirlo en la primera posición disponible del vector (tamActual++), para no violar la propiedad estructural del heap Reflotarlo sobre sus antecesores hasta situarlo en un punto en el que no se viole la propiedad de orden del heap Se usará el centinela para evitar tratar como caso especial el del nodo raíz Antes de insertar se debe comprobar si es necesario redimensionar el vector Requiere un coste constante en tiempo medio y logarítmico en caso peor EDA, T-8. Curso 02/03. N.Prieto– p.14/55 La operación insertar public void insertar (Comparable x) { comprobarTam(); int hueco=++tamActual; //posición para inserción en vector while (x.menorQue(vector[hueco/2]) { vector[hueco]=vector[hueco/2]; hueco=hueco/2; } vector[hueco]=x; } private void comprobarTam() { if (tamActual==vector.length-1) { Comparable [] vectorAnt=vector; obtenerVector(tamActual*2); for (int i=0; i<vectorAnt.length; i++) vector[i]=vectorAnt[i]; } } EDA, T-8. Curso 02/03. N.Prieto– p.15/55 Ejemplo de insertar 13 21 16 24 65 31 26 19 68 32 EDA, T-8. Curso 02/03. N.Prieto– p.16/55 Ejemplo de insertar 13 21 16 24 65 31 26 19 68 32 EDA, T-8. Curso 02/03. N.Prieto– p.17/55 Ejemplo de insertar 13 21 16 24 65 19 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.18/55 Ejemplo de insertar 13 16 24 65 19 21 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.19/55 Ejemplo de insertar 13 14 16 24 65 19 21 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.20/55 Ejercicios 1. 2. Hacer una traza de insertar el valor 3 sobre el heap <0,1,4,8,2,5,6,9,15,7,12,13> Hacer una traza de insertar a partir de un heap vacio los siguientes valores: 6,4,15,2,10,11,8,1,13,7,9,12,5,3,14 EDA, T-8. Curso 02/03. N.Prieto– p.21/55 Observaciones sobre insertar El centinela situado en la posición 0 del vector garantiza la terminación del bucle El coste del método es O(log N) si el elemento añadido fuera el nuevo mínim En promedio se requieren 2,6 comparaciones para llevar a cabo una inserción EDA, T-8. Curso 02/03. N.Prieto– p.22/55 La operación eliminarMin El acceso al elemento menor es directo, está en la posición 1 del vector Cuando se elimina este elemento se queda el hueco en la raiz, tamActual disminuye y el último elemento se debe de recolocar para eliminarlo y no violar la propiedad estructural del heap Se debe hundir el hueco en el árbol a través de los hijos menores hasta que el elemento se pueda colocar sin violar la propiedad de orden del heap Requiere un coste logarítmico tanto en tiempo medio como en caso peor EDA, T-8. Curso 02/03. N.Prieto– p.23/55 Ejemplo de eliminarMin 13 14 16 19 65 19 21 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.24/55 Ejemplo de eliminarMin 14 16 19 65 19 21 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.25/55 Ejemplo de eliminarMin 14 16 65 19 21 19 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.26/55 Ejemplo de eliminarMin 14 19 16 19 21 65 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.27/55 Ejemplo de eliminarMin 14 19 16 65 19 21 26 32 68 31 EDA, T-8. Curso 02/03. N.Prieto– p.28/55 Ejemplo de eliminarMin 14 19 16 26 65 21 31 19 68 32 EDA, T-8. Curso 02/03. N.Prieto– p.29/55 La operación eliminarMin public Comparable eliminarMin () throws DesbordamientoInferior{ if (esVacia()) throws new DesbordamientoInferior("Heap vacio"); Comparable min=vector[1]; vector[1]=vector[tamActual--]; hundir (1); return min } private void hundir (int hueco) { int hijo; boolean coloca=true; Comparable tmp=vector[hueco]; while (hueco*2<=tamActual && coloca) { hijo=hueco*2; if (hijo!=tamActual && vector[hijo+1].menorQue(vector[hijo]) hijo++; if (vector[hijo].menorQue(tmp)) { vector[hueco]=vector[hijo]; hueco=hijo; } else coloca=false; } vector[hueco]=tmp; } EDA, T-8. Curso 02/03. N.Prieto– p.30/55 Ejercicios 1. 2. 3. Hacer una traza de eliminarMin sobre el heap <0,1,4,8,2,5,6,9,15,7,12,13> Hacer una traza de hundir(3) sobre el heap <0,1,4,8,2,5,6,9,15,7,12,13> Un Heap Maximal (Max-Heap) soporta las operaciones insertar y eliminarMax. Implementad esta estructura de datos EDA, T-8. Curso 02/03. N.Prieto– p.31/55 La operacion arreglarMonticulo El objetivo es dado un arbol completo restablecer la propiedad de orden para tener un heap Coste lineal con el numero de nodos EDA, T-8. Curso 02/03. N.Prieto– p.32/55 Ejemplo de arreglarMonticulo 92 47 21 12 20 61 17 55 63 45 37 25 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.33/55 Ejemplo de arreglarMonticulo 92 47 21 i=7 12 20 61 17 55 63 45 37 25 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.34/55 Ejemplo de arreglarMonticulo 92 47 21 i=6 12 20 61 17 55 63 25 37 45 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.35/55 Ejemplo de arreglarMonticulo 92 47 21 i=5 12 20 61 17 55 63 25 37 45 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.36/55 Ejemplo de arreglarMonticulo 92 47 21 i=4 12 17 61 20 55 63 25 37 45 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.37/55 Ejemplo de arreglarMonticulo 92 47 21 12 17 61 20 55 i=3 63 25 37 45 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.38/55 Ejemplo de arreglarMonticulo 92 i=2 12 37 17 61 21 20 55 63 25 47 45 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.39/55 Ejemplo de arreglarMonticulo i=1 12 21 17 37 20 61 92 55 63 25 47 45 64 83 73 EDA, T-8. Curso 02/03. N.Prieto– p.40/55 La operación arreglarMonticulo private void arreglarMonticulo () { for (int i=tamActual/2; i>0; i--) hundir (i); } El coste temporal es lineal con el tamaño del Heap EDA, T-8. Curso 02/03. N.Prieto– p.41/55 Ordenación rápida: HeapSort Utilizaremos un Max-Heap (o Heap maximal) Supondremos que los N elementos a ordenar están en las posiciones desde 0 hasta N-1 El hijo izquierdo del nodo en posición i está en 2i+1 El derecho está en la posición siguiente Si (i!=0) el nodo padre está en (i-1)/2 EDA, T-8. Curso 02/03. N.Prieto– p.42/55 El algoritmo HeapSort 1. 2. Construir un Heap con los elementos del vector Recorremos el vector en sentido descendente, desde el final hasta la posición 1. Para cada posición, hacemos: a) Intercambiamos el valor máximo (v[0]) con el de la posición actual b) Hundimos el hueco a partir de la posición actual c) Pasamos a analizar la posición anterior EDA, T-8. Curso 02/03. N.Prieto– p.43/55 El método HeapSort public static void HeapSort (Comparable v[]) { for (int i=v.length/2; i>=0; i--) hundir2(v,i,v.length); for (int i=v.length; i>0; i--) { intercambiar(v,0,i); hundir2(v,0,i); } } EDA, T-8. Curso 02/03. N.Prieto– p.44/55 El método hundir2 private static void hundir2 (Comparable v[], int hueco, int fin) { int hijo = hueco*2+1 ; Comparable tmp = v[hueco]; boolean enc = false; while ( hijo<fin && !enc ) { if ( hijo!=fin-1 && v[hijo+1].compareTo(v[hijo])>0) hijo++ ; if ( v[hijo].compareTo(tmp)>0) { v[hueco] = v[hijo] ; hueco = hijo; hijo = hueco *2+1 ; } else enc = true; } v[hueco] = tmp; } EDA, T-8. Curso 02/03. N.Prieto– p.45/55 Ejemplo de heapSort EJEMPLO: ordenacion rapida v 16 14 10 8 0 1 2 3 7 9 3 2 4 1 4 5 6 7 8 9 16 14 10 8 2 7 4 9 3 1 EDA, T-8. Curso 02/03. N.Prieto– p.46/55 Ejemplo de heapSort 16 14 10 8 2 9 7 4 1 3 i=9 hundir2 14 1 14 8 2 7 4 16 9 10 8 10 7 4 3 2 1 9 3 16 EDA, T-8. Curso 02/03. N.Prieto– p.47/55 Ejemplo de heapSort 14 10 8 2 9 7 4 1 3 16 i=8 hundir2 10 1 4 2 7 14 16 9 9 8 10 8 4 3 2 7 1 3 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.48/55 Ejemplo de heapSort 14 10 9 8 2 1 7 4 3 14 16 i=7 hundir2 2 9 8 4 9 7 10 14 16 1 3 8 3 4 7 1 2 10 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.49/55 Ejemplo de heapSort 9 3 8 1 7 4 2 i=6 10 14 16 hundir2 2 7 10 14 16 1 3 7 3 8 4 8 9 4 2 1 9 10 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.50/55 Ejemplo de heapSort 8 3 7 1 2 4 9 i=5 10 14 16 hundir2 1 2 10 14 16 8 3 4 3 7 4 7 9 1 2 8 9 10 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.51/55 Ejemplo de heapSort 7 3 4 1 2 8 9 i=4 10 14 16 hundir2 2 7 10 14 16 8 3 2 3 4 1 4 9 1 7 8 9 10 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.52/55 Ejemplo de heapSort 4 3 2 1 i=3 7 8 9 10 14 16 hundir2 3 1 3 2 4 7 10 14 16 8 2 9 4 1 7 8 9 10 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.53/55 Ejemplo de heapSort 3 2 4 i=2 1 7 8 9 10 14 16 2 4 2 hundir2 1 1 3 7 10 14 16 8 9 4 3 7 8 9 10 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.54/55 Ejemplo de heapSort 2 1 4 3 i=1 7 8 9 10 14 16 1 2 4 v 3 7 8 1 2 0 1 3 4 7 8 9 10 14 16 2 4 5 6 3 7 8 9 9 10 14 16 EDA, T-8. Curso 02/03. N.Prieto– p.55/55