Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
Temario
•
Heap
–
Definición de Heap
–
Descripción y terminología
–
Ejemplos
–
Operaciones
•
Tablas de dispersión
–
Funciones de dispersión
–
Dispersión abierta
–
Dispersión cerrada
•
Exploración lineal.
•
Exploración cuadratica.
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Es una implementación de colas de prioridad que permite
implementar la inserción y eliminación de elementos con un
tiempo O(log N)
•
Cumple con dos propiedades:
– Propiedad estructural
– Propiedad de orden
Complejidad Temporal, Estructuras de Datos y Algoritmos
Propiedad estructural
•
Una heap es un árbol binario completo.
Complejidad Temporal, Estructuras de Datos y Algoritmos
Se almacena en un arreglo, tal que:
- La raíz está almacenada en la posición 1.
- Para un elemento que está en la posición i:
- El hijo izquierdo está en la posición 2 * i
- El hijo derecho está en la posición (2 * i) + 1
- El padre está en la posición (i / 2)
Complejidad Temporal, Estructuras de Datos y Algoritmos
- MinHeap
• El elemento mínimo está almacenado en la raíz
• El dato almacenado en cada nodo es menor o igual al
de sus hijos
- MaxHeap
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Estructura de datos y operaciones de
una Heap:
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Primero, hay que poner el nuevo elemento al final
del arreglo
9 2
13 15
5
6 7
8 90
8 90 108 3
Complejidad Temporal, Estructuras de Datos y Algoritmos
No cumple la propiedad
de orden de minheap
92
13 15
5
6 7
8 90
8 90 108 3
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Luego, se debe hacer un filtrado hacia arriba para
restaurar la propiedad de orden.
7 8 10 3 3 8 10 7 9 2 13 15 5 6 7 8 90
8 90 108 3
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
El nuevo árbol tampoco cumple la propiedad de
heap.
2
5
6 3
8 90
8 90 108 7
...
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Realizamos el filtrado hacia arriba nuevamente.
...
3
6 5
8 90
8 90 108 7
2
5
6 3
8 90
8 90 108 7
...
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Finalmente cumple con la propiedad de Heap.
9 2
13 15
3
6 5
8 90
8 90 108 7
Complejidad Temporal, Estructuras de Datos y Algoritmos
• Retorna y elimina la raíz de la Heap
• Sobreescribo la raíz con el último elemento.
9 2 13 15 3 6 5 8 90
8 90108
9 7 13 15 3 6 5 8 90
8 90108
9 2 13 15 3 6 5 8 90
8 90108 7
9 2 13 15 3 6 5 8 90
8 90108 7
• De nuevo, no cumple con la propiedad de Heap.
• Se debe hacer un filtrado hacia abajo para restaurar la propiedad de orden.
• Puedo intercambiar la raíz con la raíz de un subárbol cuyo valor sea
Complejidad Temporal, Estructuras de Datos y Algoritmos
3
• De nuevo, no cumple con la propiedad de Heap.
9
13 15
3
6 5
8 90
8 90108
9
13 15
7
6 5
8 90
8 90108
9 2 13 15 3 6 5 8 90
8 90108
9 7 13 15 3 6 5 8 90
8 90108
Complejidad Temporal, Estructuras de Datos y Algoritmos 9 13 15 3 6 5 8 90
8 90108
9 3 13 15 5 6 7 8 90
8 90108
9 2 13 15 3 6 5 8 90
8 90108
9 3 13 15 7 6 5 8 90
8 90108
• 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).
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Para construir una Heap a partir de una lista de n
elementos:
– Se pueden insertar los elementos de a uno. O(nlog(n)) • Para cada elemento [O(n)], insertamos en la heap [O(logn)]
– Alternativamente, podemos partir de un arreglo de elementos y realizar los filtrados correspondientes para que cumpla la
propiedad de orden de heap [O(n)]
• Para ello se realiza el filtrado hacia abajo de la primer mitad del arreglo, es decir, de los elementos que no son hojas.
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
La dispersión es una técnica empleada para
realizar inserciones, eliminaciones y búsquedas
en un tiempo promedio constante.
•
Un uso común de esta técnica lo representan los
diccionarios. Un diccionario almacena objetos
formados por una clave, por la cual se busca en el
diccionario, y su definición, que es lo que se
devuelve.
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
La estructura de datos ideal para la tabla de
dispersión es simplemente una lista de tamaño
fijo N que contiene las claves.
– Cada clave se hace corresponder con algún número en el intervalo entre 0 y N −1, y se coloca en la celda
correcta.
– A la correspondencia se le denomina función de dispersión.
Complejidad Temporal, Estructuras de Datos y Algoritmos
• Toda función de dispersión debe: – calcularse de forma sencilla O(1).
– distribuir uniformemente las claves.
• Por ejemplo, si las claves son números enteros, (clave % N) es una función buena, salvo que haya propiedades
indeseables:
– Si N fuese 100 y todas las claves terminasen en cero, esta función de dispersión sería una mala opción.
• Es buena idea asegurarse de que el tamaño de la tabla sea un número primo.
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Opción 1:
def disp1(str): result = 0
for c in str:
result = result + ord(c) return result % N
•
Fácil de implementar
•
Se ejecuta con rapidez.
•
No distribuye bien las claves si el tamaño de la
tabla es grande.
– Por ejemplo, si N = 10007 (un número primo), y todas las claves tienen una longitud de ocho o menos, la
función de dispersión sólo toma valores entre 0 y 1016 que es 127 * 8.
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Opcion 2:
• def disp2(str):
suma= ord(str[0])+27*ord(str[1])+729*ord(str[2])
return suma % N
•
Examina sólo los primeros tres caracteres.
•
Si son aleatorios (por ejemplo, si el tamaño de la
tabla es 10007), esperaríamos una distribución
homogénea.
•
Los lenguajes naturales no son aleatorios
.
– Un porcentaje bajo de la tabla es aprovechada.
Complejidad Temporal, Estructuras de Datos y Algoritmos
•
Opcion 3:
def disp3(str):
str_len=len(str)
pol_res = ord(str[str_len-1]) for i in range(str_len-2,-1,-1):
termino=(32**(str_len-(i+1)) * ord(str[i])) pol_res += termino
return pol_res % N
•
Intervienen todos los caracteres.
•
Se obtiene una buena distribución.
•
El código calcula una función polinómica:
Funciones de dispersión (Texto)
∑
i=0
len(str)−1
32iord(str[len(str)−(i+1)])
Complejidad Temporal, Estructuras de Datos y Algoritmos
• La estrategia consiste en tener una lista de todos los elementos que se dispersan en el mismo valor.
• Para efectuar una búsqueda, usamos la función de dispersión para determinar qué lista recorrer.
• Para efectuar un insertar, recorremos la lista adecuada para revisar si el elemento ya está en la lista. Si el elemento
resulta ser nuevo, se inserta al frente o al final de la lista.
• Además de las listas enlazadas, se podría usar un árbol
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
• En un sistema de dispersión cerrada, si ocurre una colisión, se intenta buscar celdas alternativas hasta encontrar una vacía.
– Se busca en sucesión en las celdas donde:
– La función f es la estrategia de resolución de las colisiones.
• Como todos los datos se guardan en la tabla, esta tiene que ser más grande para la dispersión cerrada que para la
abierta.
Resolución de colisiones: dispersión cerrada
d0(x), d1(x), d2(x),...
Complejidad Temporal, Estructuras de Datos y Algoritmos
• La eliminación estándar no es realizable con dispersión cerrada.
– La celda ocupada pudo haber causado una colisión en el
pasado. Por ejemplo, con exploración lineal, si las claves “x” e “y” se dispersan a la misma posición (p. ej. 2):
• Insertamos ambas claves
• • • •
• Borramos la primera
•
Complejidad Temporal, Estructuras de Datos y Algoritmos
• Aquí la estrategia de resolución de las colisiones es una función lineal de i, por lo general f (i) = i.
– Esto equivale a buscar secuencialmente en la lista (en forma circular) una posición vacía.
– Si la tabla es suficientemente grande, siempre se encontrará una celda vacía.
• Pero ello puede tomar demasiado tiempo.
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
• La función de resolución de colisiones es cuadrática, por lo general: f (i) = i² .
• Con exploración lineal es malo llenar la tabla, porque se degrada el rendimiento. Para la exploración cuadrática, la situación es más drástica:
– Con más de la mitad de la tabla ocupada, no hay garantías de encontrar una celda vacía.
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos
• Para la resolución de colisiones aplicamos una segunda función de dispersión, en general: f (i) = i * h2(x).
– La función nunca debe evaluarse a cero.
– Y es importante que todas las celdas puedan ser intentadas.
• Una función como h2(x) = R * (x % R), con R un
número primo menor que el tamaño de la tabla, funcionará bien.
• Hay que asegurarse de que el tamaño de la tabla sea primo.
Complejidad Temporal, Estructuras de Datos y Algoritmos
Complejidad Temporal, Estructuras de Datos y Algoritmos