Glab S13 Rusnayo 2023 01
Glab S13 Rusnayo 2023 01
Glab S13 Rusnayo 2023 01
LABORATORIO N° 13
HEAP
Alumno Nota
Urquizo Apaza, Josue Alessandro
Grupo D
Fecha de Entrega 19/06/2023
Docente Renato Usnayo Cáceres
OBJETIVOS:
• Conocer, comprender y aplicar el uso de Heap como una forma de almacenar datos en la
resolución de problemas de software.
SEGURIDAD:
Advertencia:
En este laboratorio está prohibida la manipulación del hardware, conexiones
eléctricas o de red; así como la ingestión de alimentos o bebidas.
FUNDAMENTO TEÓRICO:
• Revisar el texto guía que está en el campus Virtual.
NORMAS EMPLEADAS:
• No aplica
RECURSOS:
• En este laboratorio cada alumno trabajará con un equipo con Windows 10.
PROCEDIMIENTO:
Nota:
Las secciones en cursivas son demostrativas, pero sirven para que usted pueda instalar las
herramientas de desarrollo en un equipo externo.
EJERCICIO DE APLICACIÓN
Los heaps son estructuras de datos que se utilizan para almacenar y organizar elementos en función de
su valor. Son especialmente útiles cuando necesitamos acceder rápidamente al elemento de mayor o
menor valor.
En Python, los heaps se pueden implementar utilizando la biblioteca heapq. Esta biblioteca proporciona
una implementación eficiente de un heap binario.
import heapq
Para crear un heap vacío, podemos simplemente crear una lista vacía:
heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 3)
heapq.heappush(heap, 8)
Después de insertar estos elementos, el heap se verá así: [3, 5, 8]. El elemento más pequeño siempre
estará en el índice 0 del heap.
import heapq
heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 3)
heapq.heappush(heap, 8)
print(heap)
min_element = heapq.heappop(heap)
print(min_element)
import heapq
heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 3)
heapq.heappush(heap, 8)
min_element = heapq.heappop(heap)
print(min_element)
import heapq
heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 3)
heapq.heappush(heap, 8)
min_element = heapq.heappop(heap)
print(min_element)
print(heap)
También podemos convertir una lista existente en un heap utilizando la función heapq.heapify():
lista = [7, 2, 9, 1, 4]
heapq.heapify(lista)
print(lista)
Ejercicios Resueltos
Dada una lista de números, encuentra los tres elementos más grandes utilizando un heap.
def find_largest_elements(nums):
heap = []
for num in nums:
heapq.heappush(heap, num)
if len(heap) > 3:
heapq.heappop(heap)
return heap
lista_numeros = [12, 54, 23, 67, 45, 9, 41, 73]
largest_elements = find_largest_elements(lista_numeros)
print(largest_elements)
import heapq
def find_largest_elements(nums):
heap = []
for num in nums:
heapq.heappush(heap, num)
if len(heap) > 3:
heapq.heappop(heap)
return heap
heap1 = [2, 5, 8]
heap2 = [3, 6, 9]
merged_heap = merge_heaps(heap1, heap2)
print(merged_heap)
import heapq
heap1 = [2, 5, 8]
heap2 = [3, 6, 9]
merged_heap = merge_heaps(heap1, heap2)
print(merged_heap)
import heapq
heap1 = [2, 5, 8]
heap2 = [3, 6, 9]
merged_heap = merge_heaps(heap1, heap2)
print(merged_heap)
import heapq
heap1 = [2, 5, 8]
heap2 = [3, 6, 9]
merged_heap = merge_heaps(heap1, heap2)
print(merged_heap)
def heap_sort(lista):
heap = []
lista_ordenada = []
while heap:
lista_ordenada.append(heapq.heappop(heap))
return lista_ordenada
lista_desordenada = [9, 5, 2, 7, 1, 6]
lista_ordenada = heap_sort(lista_desordenada)
print(lista_ordenada) # Imprime: [1, 2, 5, 6, 7, 9]
import heapq
def heap_sort(lista):
heap = []
for elemento in lista:
heapq.heappush(heap, elemento)
lista_ordenada = []
while heap:
lista_ordenada.append(heapq.heappop(heap))
return lista_ordenada
lista_desordenada = [9, 5, 2, 7, 1, 6]
lista_ordenada = heap_sort(lista_desordenada)
print(lista_ordenada)
Hasta ahora hemos trabajado con heaps mínimos, donde el elemento mínimo siempre está en el índice
0. Ahora, vamos a implementar un heap máximo donde el elemento máximo siempre estará en el índice
0.
import heapq
class MaxHeap:
def __init__(self):
self.heap = []
def extract_max(self):
max_element = -heapq.heappop(self.heap)
return max_element
heap_max = MaxHeap()
heap_max.insert(5)
heap_max.insert(3)
heap_max.insert(8)
max_element = heap_max.extract_max()
print(max_element) # Imprime: 8
import heapq
class MaxHeap:
def __init__(self):
self.heap = []
def extract_max(self):
max_element = -heapq.heappop(self.heap)
return max_element
heap_max = MaxHeap()
heap_max.insert(5)
heap_max.insert(3)
heap_max.insert(8)
max_element = heap_max.extract_max()
print(max_element)
Dada una lista de números y un número entero k, encuentra el elemento k-ésimo más grande utilizando
un heap.
heapq.heappush(heap, num)
if len(heap) > k:
heapq.heappop(heap)
return heapq.heappop(heap)
import heapq
Implementa un heap que tenga en cuenta una prioridad personalizada para sus elementos. Cada
elemento del heap será una tupla (valor, prioridad) y el heap se ordenará en función de la prioridad.
import heapq
class CustomPriorityHeap:
def __init__(self):
self.heap = []
def extract_max(self):
_, max_element = heapq.heappop(self.heap)
return max_element
heap_prioridad = CustomPriorityHeap()
heap_prioridad.insert("Tarea 1", 2)
heap_prioridad.insert("Tarea 2", 1)
heap_prioridad.insert("Tarea 3", 3)
max_element = heap_prioridad.extract_max()
print(max_element)
import heapq
class CustomPriorityHeap:
def __init__(self):
self.heap = []
def extract_max(self):
_, max_element = heapq.heappop(self.heap)
return max_element
heap_prioridad = CustomPriorityHeap()
heap_prioridad.insert("Tarea 1", 2)
heap_prioridad.insert("Tarea 2", 1)
heap_prioridad.insert("Tarea 3", 3)
max_element = heap_prioridad.extract_max()
print(max_element)
Dadas dos listas de números, encuentra los elementos comunes entre ellas utilizando heaps.
return common_elements
lista1 = [1, 2, 3, 4, 5]
lista2 = [4, 5, 6, 7, 8]
common_elements = find_common_elements(lista1, lista2)
print(common_elements) # Imprime: [4, 5]
return common_elements
lista1 = [1, 2, 3, 4, 5]
lista2 = [4, 5, 6, 7, 8]
common_elements = find_common_elements(lista1, lista2)
print(common_elements)
Dada una lista de elementos, encuentra los k elementos más frecuentes utilizando un heap.
heap = []
for key, value in frequency.items():
heapq.heappush(heap, (-value, key))
k_most_frequent = []
for _ in range(k):
k_most_frequent.append(heapq.heappop(heap)[1])
return k_most_frequent
elements = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
k_most_frequent = find_k_most_frequent_elements(elements, 2)
print(k_most_frequent) # Imprime: [4, 3]
import heapq
heap = []
for key, value in frequency.items():
heapq.heappush(heap, (-value, key))
k_most_frequent = []
for _ in range(k):
k_most_frequent.append(heapq.heappop(heap)[1])
return k_most_frequent
elements = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
k_most_frequent = find_k_most_frequent_elements(elements, 2)
print(k_most_frequent)
Implementa un heap mínimo utilizando objetos personalizados en lugar de valores simples. Considera
una clase Persona con atributos nombre y edad. El heap se ordenará en función de la edad de las
personas.
import heapq
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
class HeapMinimo:
def __init__(self):
self.heap = []
def eliminar_minimo(self):
return heapq.heappop(self.heap)
# Ejemplo de uso
heap_personas = HeapMinimo()
heap_personas.insertar(Persona("Ana", 25))
heap_personas.insertar(Persona("Juan", 30))
heap_personas.insertar(Persona("María", 20))
La salida será:
María 20
Ana 25
Juan 30
import heapq
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
class HeapMinimo:
def __init__(self):
self.heap = []
def eliminar_minimo(self):
return heapq.heappop(self.heap)
heap_personas = HeapMinimo()
heap_personas.insertar(Persona("Ana", 25))
heap_personas.insertar(Persona("Juan", 30))
heap_personas.insertar(Persona("María", 20))
persona = heap_personas.eliminar_minimo()
print(persona.nombre, persona.edad)
Dadas múltiples listas ordenadas, une y ordena todas las listas en una sola lista utilizando un heap.
def merge_sorted_lists(listas):
heap = []
for i, lista in enumerate(listas):
if lista:
heapq.heappush(heap, (lista[0], i, 0))
merged_list = []
while heap:
val, list_idx, elem_idx = heapq.heappop(heap)
merged_list.append(val)
if elem_idx + 1 < len(listas[list_idx]):
heapq.heappush(heap, (listas[list_idx][elem_idx + 1], list_idx, elem_idx + 1))
return merged_list
import heapq
def merge_sorted_lists(listas):
heap = []
for i, lista in enumerate(listas):
if lista:
heapq.heappush(heap, (lista[0], i, 0))
merged_list = []
while heap:
val, list_idx, elem_idx = heapq.heappop(heap)
merged_list.append(val)
return merged_list
Tarea
• Diseña una función que tome dos listas de números ordenadas en forma ascendente y devuelva
la mediana de las dos listas utilizando un heap.
import heapq
list1 = [1, 3, 5, 7]
list2 = [2, 4, 6, 8]
median = find_median(list1, list2)
print("La mediana es: ", median)
• Implementa una función que tome una lista de palabras y devuelva las k palabras más
frecuentes utilizando un heap.
import heapq
top_words = find_top_k_words(word_list, 2)
print("Las palabras más frecuentes son:", top_words)
• Crea una función que tome una lista de nombres y sus respectivas edades, y devuelva el nombre
de la persona más joven y de la persona más vieja utilizando un heap mínimo y uno máximo.
import heapq
def find_joven_and_viejo(people):
joven = heapq.nsmallest(1, people, key=lambda x: x[1])
viejo = heapq.nlargest(1, people, key=lambda x: x[1])
return joven[0][0], viejo[0][0]
OBSERVACIONES:
1. Los heaps en Python, implementados a través del módulo heapq, son estructuras de datos
eficientes para mantener y operar con una colección de elementos donde el mínimo (heap
mínimo) o el máximo (heap máximo) está rápidamente accesible.
2. Los heaps en Python son ideales para problemas que requieren la selección de los elementos
más grandes o más pequeños de una colección, como encontrar los k elementos más grandes o
más pequeños.
3. La implementación de heaps en Python proporciona métodos eficientes para realizar
operaciones como la inserción de elementos, extracción del mínimo/máximo, mezcla de heaps y
ordenación en el lugar.
4. Los heaps en Python son útiles en algoritmos de búsqueda, algoritmos de grafos y algoritmos de
compresión.
5. Los heaps en Python tienen una complejidad tiempo para las operaciones como las extracciones
o inserciones del mínimo o máximo.
CONCLUSIONES:
1. Los heaps en Python están representados por listas, donde el elemento mínimo o máximo se
encuentra en la posición 0.
2. En un heap mínimo, cada nodo padre tiene un valor menor o igual que los valores de sus nodos
hijos, mientras que en un heap máximo, cada nodo padre tiene un valor mayor o igual que los
valores de sus nodos hijos.
3. Los heaps en Python son estructuras basadas en árboles binarios completos, lo que permite un
acceso eficiente a los elementos y una rápida inserción y extracción del mínimo/máximo.
4. A diferencia de otras estructuras de datos como los árboles de búsqueda binarios, los heaps en
Python no garantizan un orden total entre los elementos en el mismo nivel del heap. Solo se
garantiza el orden relativo en términos del mínimo/máximo.
5. Los heaps en Python no son tan buenos cuando necesitamos un acceso rapido a los elementos
arbitrarios que estan dentro del HEAP, ya que fueron creados para realizár operaciones de
inserción, extracción y busqueda del mínimo o máximo de una forma correcta.