La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Estructuras de Datos ● Introducción y Heaps ● Docentes: ● Eugenia Simich ● Juan Manuel Rabasedas ● Sergio Giro.

Presentaciones similares


Presentación del tema: "Estructuras de Datos ● Introducción y Heaps ● Docentes: ● Eugenia Simich ● Juan Manuel Rabasedas ● Sergio Giro."— Transcripción de la presentación:

1 Estructuras de Datos ● Introducción y Heaps ● Docentes: ● Eugenia Simich ● Juan Manuel Rabasedas ● Sergio Giro

2 Cómo empezar?

3 ● Mi definición: ”Organización sistemática de los datos para permitir una administración eficiente de los mismos usando un conjunto de operaciones”

4 Cómo empezar? ● Mi definición: ”Organización sistemática de los datos para permitir una administración eficiente de los mismos usando un conjunto de operaciones” ● Wikipedia: ”Es una manera particular de guardar y organizar datos en una computadora para que puedan ser usados de manera eficiente”

5 Ejemplos ● (No necesariamente informáticos) ● Agenda (organización sistemática? operaciones? eficientes?) ● Guía telefónica ● Planilla ● Guía turística ● Mapa de la ciudad

6 Arreglos/vectores ● Usos: geometría cartesiana (entre otros) ● Operaciones necesarias: ● Poner el valor para una componente ● Tomar el valor de una componente ● Operaciones derivadas: ● Suma, producto interno...

7 Arreglos/vectores ● Organización sistemática:

8 Arreglos/vectores ● Organización sistemática: ● Organizo las componentes como factores primos de un número ● (4,1,8) → = 18750000 ● Leer la n-sima componente: descomponer el número y obtener la potencia correspondiente al n- simo primo ● Asignar la n-sima componente: dividir por p^{m} y multiplicar por p^{n}. Donde p es el n-simo primo, m es el valor anterior y n es el nuevo valor

9 Arreglos/vectores ● Organización sistemática: ● En un modelo de memoria lineal: ● Reservo espacio para n enteros a partir de la posicion b ● La n-sima componente es el entero en la posicion b+n ● Leer la n-sima componente: buscar el entero en la posicion b+n ● Asignar la n-sima componente: poner el nuevo valor en la posicion b+n

10 Arreglos/vectores ● Operaciones: ● Crear: Int → Arreglo ● Leer: Arreglo x Int → Int ● Asignar: Arreglo x Int x Int→ Arreglo ● Leer(a,i) se anota a[i] ● Asignar(a,i,j) es arreglo a despues de hacer a[i] = j ● Crear(n) en lenguaje C: malloc(n*sizeof(int))

11 Arreglos/vectores ● Operación derivada: producto interno ● prod: Arreglo x Arreglo → Int ● int prod (a,b,n) { ● int res = 0; ● for(int i = 0; i < n; i++) { ● res += a[i]*b[i]; ● } ● return res; ● }

12 (Min) Heaps ● Estructura de datos con las siguientes operaciones ● insertar : Heap x Int → Heap ● borrar_min : Heap → Heap ● obtener_minimo : Heap → Int ● Se utiliza para implementar colas de prioridad (priority queues)

13 (Min) Heaps ● Los heaps son colas de prioridad en las que los datos pueden recorrerse en forma de árbol ● En cada subárbol, la raíz es el elemento mínimo del subárbol 9 2 5 67 1010

14 (Min) Heaps ● Para explicitar la estructura de árbol podemos agregar una operación adicional: ● descomponer: Heap → Heap x Int x Heap 9 2 5 67 1010 5 67 5 67 5 67 2 9 1010

15 Representación ● Podemos representar un árbol (y por lo tanto un heap) utilizando arreglos 9 2 1313 1515 5 67 8 9090 8 9090 8 9090 1010 4040 8 9090 1414 2525 8 9090 2424 2323 0 12 3 46 5 7891011121314 2 5 9 6 7 13 15 8 90 10 40 14 25 24 23 0 01 2 3 4 5 6 7 8 9 10 11 12 13 14 ● Se puede probar por inducción: ● el hijo izquierdo del nodo n está en la posición 2n+1 ● el hijo derecho en la posición 2n+2 ● padre(n) = (n-1) div 2

16 Representación descomponer(h) = descomponer( (a,r,s) ) = ((a,2r+1,s), a[r], (a,2r+2,s)) 9 2 1313 1515 5 67 8 9090 8 9090 8 1010 0 12 3 4 789 0 5 6 ● Para implementar la función descomponer podemos tener, además del arreglo, un entero r indicando la raíz ● Para saber si un nodo tiene hijos, alcanza con guardar la ultima posicion ocupada ● h = (a,r,s)

17 Implementación de las operaciones 9 2 1313 1515 5 67 8 9090 8 9090 8 1010 0 12 3 4 789 0 5 6 ● insertar: puedo poner el nuevo elemento al final del arreglo 3

18 Implementación de insertar 9 2 1313 1515 5 67 8 9090 8 9090 8 1010 0 12 3 4 789 0 5 6 ● insertar: puedo poner el nuevo elemento al final del arreglo ● No cumple la propiedad de heap 3

19 Implementación de insertar 9 2 1313 1515 5 67 8 9090 8 9090 8 1010 0 12 3 4 789 0 5 6 ● insertar: puedo poner el nuevo elemento al final del arreglo ● No cumple la propiedad de heap ● Podemos hacer que el subarbol cumpla la propiedad intercambiando el valor con el nodo superior 3 7 8 1010 4 9 3 7 8 1010 4 9 3 3 8 1010 4 9 7

20 Implementación de insertar 2 5 63 8 9090 8 9090 8 1010 0 1 3 4 789 ● El nuevo árbol tampoco cumple la propiedad de heap 7...

21 Implementación de insertar 2 5 63 8 9090 8 9090 8 1010 0 1 3 4 789 ● El nuevo árbol tampoco cumple la propiedad de heap ● Pero puedo intercambiar nuevamente 7... 3 65 8 9090 8 9090 8 1010 1 3 4 7 7

22 Implementación de insertar 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 0 12 3 4 789 0 5 6 ● Finalmente cumple con la propiedad de heap 7

23 Implementación de insertar 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 0 12 3 4 789 0 5 6 ● insertar ( (a,r,s), n) es un heap (a',r',s') en el que: ● s' = s+1 ● r' = r ● a' es el arreglo luego de ejecutar: a[s+1] = n; flotar(a,s+1); 7 10

24 Implementación de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● void swap(int a[], int p, int q) { ● int aux = a[p]; ● a[p] = a[q]; ● a[q] = aux; ● } ● int padre(int i){ if(i ==0) return 0; return (i-1)/2; }

25 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Sea c el valor de la variable r al comenzar el bucle, d el valor de r al terminar, sea a' el valor del arreglo al terminar ● Debemos demostrar a'[u] <= a'[t] para todo u, t tal que t es descendiente de u, t != d ● Consideramos diferentes casos para t y u ● Caso t = c Si u = padre(c), dado que entramos al bucle, teníamos a[c] = a'[padre(c)] = a'[u] u c = t ` u ` < >

26 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Sea c el valor de la variable r al comenzar el bucle, d el valor de r al terminar, sea a' el valor del arreglo al terminar ● Debemos demostrar a'[u] <= a'[t] para todo u, t tal que t es descendiente de u, t != d ● Consideramos diferentes casos para t y u ● Caso t = c Si u != padre(c), por hipótesis a[u] <= a[d] = a'[c] d c = t ` u ` < > d u <=

27 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Sea c el valor de la variable r al comenzar el bucle, d el valor de r al terminar, sea a' el valor del arreglo al terminar ● Debemos demostrar a'[u] <= a'[t] para todo u, t tal que t es descendiente de u, t != d ● Consideramos diferentes casos para t y u ● Caso t = padre(c) En este caso t = d, no debemos demostrar nada d = padre(c) = t c ` c ` < >

28 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Sea c el valor de la variable r al comenzar el bucle, d el valor de r al terminar, sea a' el valor del arreglo al terminar ● Debemos demostrar a'[u] <= a'[t] para todo u, t tal que t es descendiente de u, t != d ● Consideramos diferentes casos para t y u ● Caso u = c Como la invariante valía, antes del bucle tenemos a[d] <= a[t]. Después del bucle a'[u] = a'[c] = a[d] <= a[t] = a'[t] c = u t ` d t ` d <=

29 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Sea c el valor de la variable r al comenzar el bucle, d el valor de r al terminar, sea a' el valor del arreglo al terminar ● Debemos demostrar a'[u] <= a'[t] para todo u, t tal que t es descendiente de u, t != d ● Consideramos diferentes casos para t y u ● Caso u = c Como la invariante valía, antes del bucle tenemos a[d] <= a[t]. Después del bucle a'[u] = a'[c] = a[d] <= a[t] = a'[t] c = u t ` d t ` d <=

30 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Sea c el valor de la variable r al comenzar el bucle, d el valor de r al terminar, sea a' el valor del arreglo al terminar ● Debemos demostrar a'[u] <= a'[t] para todo u, t tal que t es descendiente de u, t != d ● Consideramos diferentes casos para t y u ● Caso u = padre(c) Suponemos t != c (el caso u = padre(c), t = c fue el primero que vimos). En este caso a'[u] = a[c] < a[u] <= a[t] = a'[t] c t ` d = u = padre(c) t ` c d <= ><

31 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Sea c el valor de la variable r al comenzar el bucle, d el valor de r al terminar, sea a' el valor del arreglo al terminar ● Debemos demostrar a'[u] <= a'[t] para todo u, t tal que t es descendiente de u, t != d ● En los otros casos la prueba es trivial (los valores de a y a' sólo cambian para c y padre(c) )

32 Corrección de insertar ● void flotar(int a[], int r) { ● while(padre(r) != r ● && a[r] < a[padre(r)]) { ● swap(a,r,padre(r)); ● r = padre(r); ● } ● Invariante: al finalizar el bucle, vale la propiedad de heap excepto que puede ser a[u] > a[r] si r desciende de u ● Una vez que el bucle sale, a[padre(r)] <= a[r]. Además, como vale la invariante, para todos los ancestros u de padre(r) tenemos a[u] <= a[padre(r)]. Por ende, a[u] <= a[r] para todo ancestro u de r. Junto con la invariante, esto asegura a[u] <= a[t] para todo u ancestro de t

33 Implementacion de borrar_min ● Sobreescribo la raíz con el último elemento 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 9 7 1313 1515 3 65 8 9090 8 9090 8 1010 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 7 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 7 ● De nuevo, no cumple con la propiedad de heap ● Puedo intercambiar la raíz con la raíz de un subárbol cuyo valor sea mínimo

34 Implementacion de borrar_min ● Sobreescribo la raíz con el último elemento 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 9 3 1313 1515 7 65 8 9090 8 9090 8 1010 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 9 7 1313 1515 3 65 8 9090 8 9090 8 1010 ● De nuevo, no cumple con la propiedad de heap ● Puedo intercambiar la raíz con la raíz de un subárbol cuyo valor sea mínimo

35 Implementacion de borrar_min ● Sobreescribo la raíz con el último elemento 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 9 3 1313 1515 5 67 8 9090 8 9090 8 1010 9 2 1313 1515 3 65 8 9090 8 9090 8 1010 9 3 1313 1515 7 65 8 9090 8 9090 8 1010 ● De nuevo, no cumple con la propiedad de heap ● Puedo intercambiar la raíz con la raíz de un subárbol cuyo valor sea mínimo (notar que si subía el 6, quedaba el 6 sobre el 5). En este caso el 7 ”se hunde”

36 Implementacion de borrar_min ● borrar(a,r,s) = (a', r', s') ● donde ● s'=s-1 ● r' = r ● a' es el arreglo a después de hacer: a[0] = a[s]; hundir(a,0,s-1); void hundir(int a[], int pos, int size) { int swapPos=pos; if(hijo_izq(pos) <= size && a[hijo_izq(pos)] < a[pos]) { swapPos = hijo_izq(pos); } //swapPos tiene la posición con valor // mínimo entre pos e hijo_izq(pos) if(hijo_der(pos) <= size && a[hijo_der(pos)] < a[swapPos]) { swapPos = hijo_der(pos); } //swapPos tiene la posición con valor // mínimo entre pos, hijo_izq(pos) e // hijo_der(pos) if (pos != swapPos) { swap(a, pos, swapPos); hundir(a, swapPos); } }


Descargar ppt "Estructuras de Datos ● Introducción y Heaps ● Docentes: ● Eugenia Simich ● Juan Manuel Rabasedas ● Sergio Giro."

Presentaciones similares


Anuncios Google