ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort...

32
12: Heap 1 ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort Tomás Arredondo Vidal Este material está basado en: Robert Sedgewick, "Algorithms in C", (third edition), Addison-Wesley, 2001 Thomas Cormen et al, “Algorithms”, (eighth edition), MIT Press, 1992. material del curso ELO320 del Prof. Leopoldo Silva material en el sitio http://es.wikipedia.org

Transcript of ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort...

Page 1: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 1

ELO320 Estructuras de Datos y Algoritmos

Heap & HeapSort

Tomás Arredondo Vidal

Este material está basado en:

Robert Sedgewick, "Algorithms in C", (third edition), Addison-Wesley, 2001 Thomas Cormen et al, “Algorithms”, (eighth edition), MIT Press, 1992. material del curso ELO320 del Prof. Leopoldo Silva material en el sitio http://es.wikipedia.org

Page 2: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 2

12-Heap

12.1 Definicion12.2 Operaciones12.3 Heap12.4 Heapsort

Page 3: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 3

Definiciones

Se desea disponer de una estructura de datos y encontrar los algoritmos asociados que sean eficientes para seleccionar un elemento de un grupo.

Uno de los valores de la información agrupada en la estructura se denomina prioridad. Es un valor entero, y por tradición, el menor valor entero está asociado a la estructura que tiene mayor prioridad.

Prioridad se entiende como sinónimo de lo más importante. Puede haber varias estructuras con igual prioridad; en este sentido no son conjuntos.

Page 4: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 4

12-Heap

12.1 Definicion12.2 Operaciones12.3 Heap12.4 Heapsort

Page 5: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 5

Operaciones

Se definen dos operaciones: – Insertar un elemento en el conjunto, y – otra que busca y descarta (selecciona) el elemento

con valor menor del campo prioridad. Pueden haber nodos con la misma prioridad. Es necesario encontrar una nueva estructura, ya que

las vistas anteriormente tienen limitaciones. Una lista ordenada en forma ascendente por la

prioridad, permite seleccionar el mínimo con costo O(1).

Page 6: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 6

Operaciones

La inserción, manteniendo en orden tiene costo promedio O(n); si encuentra el lugar para insertar a la primera es costo 1; pero si debe recorrer toda la lista, debe efectuar n comparaciones; en promedio debe efectuar un recorrido de n/2 pasos.

Una lista no ordenada, tiene costo de inserción O(1), y búsqueda O(n).

En ambos casos la repetición de n operaciones sobre la estructura da origen a complejidad O(n2).

Estudiaremos usar la estructura de un árbol binario modificada, ya que ésta garantiza operaciones de inserción y descarte de complejidad O( log2 (n) ).

Page 7: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 7

12-Heap

12.1 Definicion12.2 Operaciones12.3 Heap12.4 Heapsort

Page 8: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 8

Altura y Complejidad La altura, es importante para la complejidad, ya que

define el número de nodos a revisar en una trayectoria.ta las hojas.

Se tienen para árboles de altura tres, los casos con n=4, 5, y 6. Es decir para n >= 23-1 y n < 23-1

Para árboles incompletos de altura h se tienen árboles con nodos en el intervalo: 23-1 <= n < 23-1

Page 9: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 9

Altura y Complejidad II Lo que implica: log2(n+1) < h <= log2(n) + 1 Se puede encontrar un n0 y un c tal que c*log2(n+1)

sea una cota superior para h. Entonces: h = O(log2(n) )

Page 10: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 10

Heap Escogemos un árbol binario parcialmente completo, lo

más balanceado posible; que podemos definir como un árbol que en su nivel más bajo (cerca de las hojas) cumple con la condición de que las hojas que le faltan están a la derecha de las presentes.

Además debemos definirlo como parcialmente ordenado, ya que es posible tener elementos repetidos. Esta condición la logramos estableciendo, que los nodos queden ordenados según:

valor (hijo) >= valor (padre)

Page 11: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 11

Heap II

Dado que el valor(hijo) >= valor (padre) Si el elemento a insertar tiene un valor menor que su

padre, debe ascender por intercambio. Si se descarta la raíz, para mantener la estructura,

se reemplaza la posición vacante en la raíz por la hoja ubicada más a la derecha, y si ésta es mayor que los hijos se la hace descender por intercambio.

Ambas operaciones tienen complejidad O(a), donde a es la altura del árbol. Esta estructura se denomina heap. Que equivale, en español, a grupo de cosas unas al lado de otras (montón, colección).

Page 12: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 12

Heap III Se visualiza como un árbol, pero el valor de cualquier

nodo es menor o igual a los valores de los nodos hijos. Se agregan nodos primero en el sub-árbol izquierdo, y

luego en el derecho, manteniendo un árbol binario lo más balanceado posible.

De esta forma el nodo de mayor prioridad (el de menor valor) se encuentra ubicado en la raíz.– La estructura anterior puede almacenarse en un

arreglo.

Page 13: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 13

Heap como Arreglo La clave de la raíz se almacena en el primer elemento

del arreglo, con índice 1 (no se usa el 0); – luego se almacenan los nodos de primer nivel (de

izquierda a derecha); – luego los de segundo nivel (siempre de izquierda a

derecha) y así sucesivamente; el último presente debe marcarse con el cursor last.

Page 14: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 14

Heap como Arreglo II De este modo:

– la raiz tiene el índice 1, – el hijo izquierdo del nodo i tiene el índice 2*i,– el hijo derecho del nodo i, si existe, tiene el índice:

2*i + 1, – el padre del nodo i, tiene el índice: i/2, – el nodo no existe si: (i < 1) o (i > last).

Page 15: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 15

Complejidad del Heap En el caso del heap, como veremos a continuación, la

inserción tiene complejidad log2(n); La extracción del mínimo, manteniendo el heap,

también es log2(n). Si se realizan n operaciones en un heap éstas tienen un

costo: nlog2(n). Como veremos más adelante se requieren realizar n

operaciones para formar un heap a partir de un arreglo desordenado, mostrando de este modo que el heap puede emplearse para desarrollar un eficiente algoritmo de ordenamiento.

Page 16: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 16

Operaciones en el Heap Se ilustra la inserción de un nodo con valor 13. Se agrega al final, y luego se lo hace ascender,

manteniendo la propiedad del heap: – El valor de cualquier nodo es menor o igual a los

valores de los nodos hijos. El algoritmo se denomina sift-up (filtrar, separar,

examinar).

Page 17: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 17

Operaciones en el Heap II El número de comparaciones es el del número de nodos

desde una hoja hasta la raíz en un árbol binario, lo más balanceado posible (este número es log(n) ).

Solo es necesario comparar el valor del nodo con el valor del padre del nodo, ya que el hermano tiene un valor mayor o igual que el del padre.

Se intercambia el nodo con valor 18 y el reciéninsertado. Aún no se cumple la propiedad de ser un heap.

Page 18: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 18

Operaciones en el Heap III Debe continuarse la revisión, en forma ascendente hacia

la raíz, para que se mantenga la propiedad del heap. Y debe intercambiarse el nodo de valor 13, con su padre, el nodo 16.

Comparando con la raíz, se advierte que el recién insertado no debe intercambiarse. Luego de estas operaciones, se mantiene la propiedad del heap.

Page 19: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 19

Heap: Definiciones y estructura de datos Definiremos un tipo de datos denominado registro, que contenga la

prioridad y agregaremos ntarea como dato que contiene el registro.typedef struct nn1{

int prioridad; int ntarea;

} registro, *preg;

#define Ntareas 10 registro r[Ntareas+1];

int last=0; /* Apunta al último */registro Tarea; /*se asume un registro iniciado con valores */ preg nuevo=&Tarea

Page 20: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 20

Heap: siftup Siftup() se implementa como descrita previamente.void siftup(int n) {

int i, j; registro temp; for (j=n; j>1; j=i) { /*Al inicio j apunta al último ( n ) */

i=j/2 ; /* i es el cursor del padre de j*/ if ( r[i].prioridad <= r[j].prioridad )

break; // Sale del for si esta en formato heap. temp=r[j]; r[j]= r[i]; r[i]=temp; /* intercambio si hijo < padre*/

/* La condición de reinicio hace que j apunte a su padre. j=i; */ }

}

Page 21: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 21

Heap: insert insert() se apoya en siftup( ) para reordenar el arbol en heap.

void insert(preg nuevo) {

last++; r[last]=*nuevo; /* Antes se tenía un heap(1, last-1) */ siftup(last); /* Luego de sift-up se tiene un heap(1, last) */

}

Page 22: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 22

Heap: siftdown Se saca elemento en la raiz, una vez extraida se intercambia con el

elemento apuntado por last y hace un siftdown para manter el heap.void siftdown(int n) { // n es el elemento mayor en el heap

int i=1, j=2*i; registro temp; /* al inicio i apunta a la raíz; j al hijo izquierdo */ while (j <=n) {

if ( ( (j+1) <=n ) && ( r[j+1].prioridad < r[j].prioridad)) j++; /* j apunta al menor de los hijos */

if (r[i].prioridad <= r[j].prioridad) break; // esta en formato heap

temp=r[j]; r[j]=r[i]; r[i]=temp; /* intercambia hijo < padre */ i=j; // nueva raiz en descensoj=2*i; // nuevo hijo izquierdo en descenso

} }

Page 23: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 23

Heap: extraer Se saca elemento en la raiz, una vez extraida se intercambia con el

elemento apuntado por last y hace un siftdown para manter el heap.

int extraemin(void) { if (last>=1) {

Tarea = r[1] ; // Salva raiz printf(" %d ", Tarea.ntarea); // Hace algo con la tarea r[1]=r[last--]; // Mueve ultimo a raíz , decrementa last. siftdown(last); // Lo hace descender, manteniendo heap. return(0);

} else

return(1); /*error intento extracción en heap vacio*/ }

Page 24: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 24

12-Heap

12.1 Definicion12.2 Operaciones12.3 Heap12.4 Heapsort

Page 25: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 25

Heapsort Debido al gran número de algoritmos para ordenar, se estudiarán

en detalle dos de los algoritmos más conocidos y eficientes. Heapsort en peor caso es O(n*log2(n)) y es una refinación del

método de selección. Los primeros en exponer este algoritmo fueron: J.W.J. Williams y

Robert Floyd (1964). Algoritmo Heapsort:

Se forma un heap, a partir del arreglo desordenado. Luego, repetidamente se intercambia la raíz con la posición del último, y se hace descender la nueva raíz en un heap de largo disminuido en uno. El arreglo queda ordenado en forma descendente.

Page 26: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 26

Heapsort: formación de heap Se analiza primero la formación de un

heap, dado un arreglo no ordenado: Existen dos procedimientos para la

formación de un heap a partir de un arreglo desordenado.

La primera manera se logra con: for(i=last/2; i>0; i--)

siftdown(i, last); i = 4

Page 27: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 27

Heapsort: formación de heap Finalmente luego de

siftdown(1,8) desciende la raiz y se logra formar un heap.

Esto se logra con un costo T(n)=(n/2)log(n) es decir O(nlogn)

Page 28: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 28

Heapsort: siftdown Se modifica levemente la rutina vista en colas de prioridad, se pasa

i de variable local, a argumento de la función.void siftdown(int i, int n){ int j; registro temp; /* al inicio i apunta a la subraíz; j al hijo izquierdo */ while ( (j=(i<<1)) <= n ) { /* j = 2*i */ if ( ( (j+1) <= n ) && ( r[j+1].prioridad < r[j].prioridad)) j++; /*Si hay hijo der. y es menor que el izq., j apunta al der. */ if (r[i].prioridad <= r[j].prioridad) break; /*Intercambia si el hijo menor es menor que el padre */ temp=r[j]; r[j]= r[i]; r[i]=temp; i=j; /* Nueva raíz en el descenso */ }}

Page 29: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 29

Heapsort: siftdown De esta forma la función forma un heap(i, n). En la primera iteración con n=8 e i=4, no se producen cambios. Se revisa el subárbol del padre del último.

Page 30: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 30

Heapsort: siftup Formar el heap también se logra con:

for(i=last; i>last/2; i--) siftup(i);

Tambien tiene una complejidad O(nlogn) La version siftup():void siftuph(int n) //inserta en posición n-ésima y lo hace ascender { int i, j;

registro temp; for (j=n; j>1; j=i) { /*Al inicio j apunta al último ( n ) */

i=(j>>1) ; /* i= j/2 donde i es el cursor del padre de j*/ if ( r[i].prioridad <= r[j].prioridad )

continue; //Si el ascenso no es en un heap, debe llegar hasta la raíz. temp=r[j], r[j]= r[i], r[i]=temp; /* intercambio si hijo < padre*/ /* La condición de reinicio hace que j apunte a su padre. j=i */ }

}

Page 31: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 31

Heapsort: ordenamiento El ordenamiento del heap se logra con:

– Repetidamente se intercambia la raíz con la posición del último,

– y se hace descender la nueva raíz en un heap de largo disminuido en uno.

for(i=last; i>1; i--) { temp=r[1]; r[1]=r[i]; r[i]=temp; /*swap(1, i) */

siftdown(1, i-1);

} Como se realiza n veces el lazo for, si se asume costo

constante para el intercambio, se tiene un costo: (n)*(log(n) +1) que es O(n*log(n)).

El algoritmo ordena en forma descendente.

Page 32: ELO320 Estructuras de Datos y Algoritmos Heap & HeapSort ...profesores.elo.utfsm.cl/~tarredondo/info/datos-algoritmos/ELO-320... · Heapsort Debido al gran número de algoritmos para

12: Heap 32

Heapsort: código Un codigo para ordenar usando heapsort, ini debe ser siempre

1, salvo que se modifiquen las rutinas de ascenso y descenso. void heapsort(preg a, Indice ini, Indice last) {

int i; registro temp; // otra opcion: for(i=last; i>last/2; i--) siftuph(a, ini, i); // ordena trayectos desde las hojas hasta la raiz

for(i=last/2; i>ini-1; i--) siftdown(a, i, last); // ordena subárboles

// desde padre del último for(i=last; i>ini; i--) {

temp=a[ini]; /*swap(ini, i) */ a[ini]= a[i]; a[i]=temp; siftdown(a, ini, i-1);

} }