ν Heap
Heap ?
- β무μμΈκ°λ₯Ό 차곑차곑 μμμ¬λ¦° λλ―Έβ λ₯Ό λ»ν¨
- μμ μ΄μ§ νΈλ¦¬μ μΌμ’
- λ°°μ΄λ‘ ꡬν κ°λ₯
- νμ λ°°μ΄μμ μΌλ°μ μΌλ‘ 0λ² μΈλ±μ€λ₯Ό μ¬μ©νμ§ μκ³ 1λ² μΈλ±μ€λ₯Ό 루νΈλ‘ μ‘μ
- μ¬λ¬ κ°μ κ°λ€ μ€μμ μ΅λκ°μ΄λ μ΅μκ°μ λΉ λ₯΄κ² μ°Ύμλ΄λλ‘ λ§λ€μ΄μ§ μλ£κ΅¬μ‘°
- νμ μΌμ’ μ λ°μ λ ¬ μνλ₯Ό μ μ§νλ€(ν° κ°μ΄ μμ λ 벨μ μκ³ μμ κ°μ΄ νμ λ 벨μ μλ€λ μ λ)
-
λ£¨νΈ λ Έλμ μ°μ μμκ° λμ λ°μ΄ν°λ₯Ό μμΉμν€λ μλ£κ΅¬μ‘°
- μ΅λ ν(max heap)κ³Ό μ΅μ ν(min heap)μ΄ μμ
- μ΅λ ν Max Heap
- μ΄λ€ λ Έλμ ν€κ° μμμ ν€λ³΄λ€ μμ§ μμ νΈλ¦¬ (μ§μ μ°κ²°λ μμ-λΆλͺ¨ λ Έλ κ°μ ν¬κΈ°λ§ λΉκ΅)
- μ΅μ ν Min Heap
- μ΄λ€ λ Έλμ ν€κ° μμμ ν€λ³΄λ€ ν¬μ§ μμ νΈλ¦¬ (μ§μ μ°κ²°λ μμ-λΆλͺ¨ λ Έλ κ°μ ν¬κΈ°λ§ λΉκ΅)
- μ΅λ ν Max Heap
- λ
Έλ μ μ«μλ λ°°μ΄μ μΈλ±μ€λ₯Ό μλ―Έν¨
- index(parent) = β£index(child)/2β¦
- index(left_child) = index(parent) * 2
- index(right_child) = index(parent) * 2 + 1
[μ΅λ νμ λ°°μ΄ νν]
μ΅λ ν μ½μ (push)
1) λ§μ§λ§ μμ λ€μμ μΈλ±μ€μ μ½μ 2) λΆλͺ¨ λ Έλμ ν¬κΈ° λΉκ΅ (max/min heapμ νΉμ±μ μ μ§νκΈ° μνμ¬) 3) heapμ νΉμ±μ΄ κΉ¨μ Έμλ€λ©΄ λΆλͺ¨ λ Έλμ λ°κΏ 4) λΆλͺ¨ λ Έλμ λΉκ΅νμ¬ heapμ νΉμ±μ΄ μ μ§λλ€λ©΄ stop
[μ΅λ νμ push]
μ΅λ ν μμ (pop)
1) νμμ μμ λ νΈλ¦¬μ root λ
Έλλ§ μμ λ° μ‘°ν κ°λ₯
2) λ£¨νΈ λ
Έλμ μμλ₯Ό μμ β μμ μ΄μ§ νΈλ¦¬ x
1) νμ λ§μ§λ§ μμλ₯Ό λ£¨νΈ λ
Έλλ‘ λ§λ¦(temp root) β μμ μ΄μ§ νΈλ¦¬ o,μ΅λ ν νΉμ± x
2) νμ νΉμ±μ λλ¬ν λκΉμ§ μ¬λ°°μΉ
#νμ μ μ₯ν μμλ₯Ό Element classλ‘ μ μ
class Element:
def __init__(self, key):
self.key=key
# MaxHeap ν€ μμ±μ μ§λ μμ μ§ν©
class MaxHeap:
MAX_ELEMENTS=100
def __init__(self):
# λ°°μ΄μ 1λ² μΈλ±μ€λΆν° ν€κ° μ½μ
λκΈ° λλ¬Έμ +1κ°μ λ°°μ΄ μμ±
self.arr=[None for i in range(self.MAX_ELEMENTS+1)]
#heapsize : νμ μ μ₯λ ν€ κ°μ, νμμλ λ§μ§λ§ ν€μ μΈλ±μ€
self.heapsize=0
# νμ΄ λΉμ΄μμΌλ©΄ True, μλλ©΄ Falseλ₯Ό λ°ν
def is_empty(self):
if self.heapsize==0:
return True
return False
# νμ΄ κ°λ μ°ΌμΌλ©΄ True, μλλ©΄ Falseλ₯Ό λ°ν
def is_full(self):
if self.heapsize>=self.MAX_ELEMENTS:
return True
return False
# λΆλͺ¨ λ
Έλμ μΈλ±μ€λ₯Ό λ°μμ΄
def parent(self, idx):
return idx >> 1
# μΌμͺ½ μμ λ
Έλμ μΈλ±μ€λ₯Ό λ°μμ΄
def left(self, idx):
return idx << 1
# μ€λ₯Έμͺ½ μμ λ
Έλμ μΈλ±μ€λ₯Ό λ°μμ΄
def right(self, idx):
return (idx << 1) + 1
# νμ μμλ₯Ό μ½μ
def push(self, item):
if self.is_full():
raise IndexError("the heap is full!!")
# λ§μ§λ§ μμμ λ€μ μΈλ±μ€
self.heapsize+=1
cur_idx=self.heapsize
#cur_idxκ° λ£¨νΈκ° μλκ³
#itemμ keyκ° cur_idx λΆλͺ¨μ ν€λ³΄λ€ ν¬λ©΄
while cur_idx!=1 and item.key > self.arr[self.parent(cur_idx)].key:
self.arr[cur_idx]=self.arr[self.parent(cur_idx)]
cur_idx=self.parent(cur_idx)
self.arr[cur_idx]=item
# νμμ μ΅λ μμλ₯Ό μμ νλ©΄μ λ°ν
def pop(self):
if self.is_empty():
return None
#μμ λ ν λ°νλ μμ
rem_elem=self.arr[1]
# 맨 λ§μ§λ§μ μμΉν μμλ₯Ό λ°μμ¨ ν
# ν μ¬μ΄μ¦λ₯Ό μ€μ΄λ©΄ μμ μ΄μ§ νΈλ¦¬ νΉμ±μ μ μ§ν μ μλ€.
temp=self.arr[self.heapsize]
self.heapsize-=1
#루νΈμμ μμ
cur_idx=1
# 루νΈμ μΌμͺ½ μμ
child = self.left(cur_idx)
# λ§μ½ child > heapsize μ΄λ©΄
# arr[cur_idx]λ 리ν λ
Έλμ΄λ€
while child <= self.heapsize:
# μ€λ₯Έμͺ½ μμμ΄ μκ³
# μ€λ₯Έμͺ½ μμμ ν€κ° μΌμͺ½ μμμ ν€λ³΄λ€ ν¬λ©΄
# childλ₯Ό μ€λ₯Έμͺ½ μμμΌλ‘
if child < self.heapsize and \
self.arr[self.left(cur_idx)].key < self.arr[self.right(cur_idx)].key:
child = self.right(cur_idx)
# μ΅λ ν νΉμ±μ λ§μ‘±νλ©΄
# λ°λ³΅λ¬Έμ λμ¨λ€.
if temp.key >= self.arr[child].key:
break
# ν€κ° ν° μμ μμλ₯Ό λΆλͺ¨λ‘ μ΄λμν¨λ€
# cur_idxλ μμ μμλ‘ μ΄λνλ€.
self.arr[cur_idx]=self.arr[child]
cur_idx=child
child=self.left(cur_idx)
self.arr[cur_idx]=temp
return rem_elem
# ν λ΄λΆμ μλ arrλ₯Ό
# μ§μ νμΈνκΈ° μν ν¨μ
def print_heap(h):
for i in range(1, h.heapsize+1):
print("{}".format(h.arr[i].key), end=" ")
print()
if __name__=="__main__":
h=MaxHeap()
h.push(Element(2))
h.push(Element(14))
h.push(Element(9))
h.push(Element(11))
h.push(Element(6))
h.push(Element(8))
print_heap(h)
while not h.is_empty():
rem=h.pop()
print(f"poped item is {rem.key}")
print_heap(h)
μ°μ μμ ν Priority Queue
Priority Queue?
- μ΅λ μ°μ μμ ν(Max Priority Queue)μ μ΅μ μ°μ μμ ν(Min Priority Queue)κ° μμ
- μ°μ μμ νλ νμΌλ‘ ꡬννλ κ²½μ°κ° λ§μ
from heapq import heappush, heappop
class Element:
def __init__(self, key, string):
self.key=key
self.data=string
class MinPriorityQueue:
def __init__(self):
self.heap=[]
def is_empty(self):
if not self.heap:
return True
return False
def push(self, item):
heappush(self.heap, (item.key, item.data))
def pop(self):
return heappop(self.heap)
def min(self):
return self.heap[0]
if __name__=="__main__":
pq=MinPriorityQueue()
pq.push(Element(2, "kim"))
pq.push(Element(14, "park"))
pq.push(Element(9, "choi"))
pq.push(Element(11, "lee"))
pq.push(Element(6, "yang"))
pq.push(Element(8, "jang"))
while not pq.is_empty():
elem=pq.pop()
print(f"key[{elem[0]}] : data[{elem[1]}]")