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

Documentos relacionados