๐จ๐ซ ์ฐ์ ์์ ํ๋ max-heap ๋๋ min-heap์ ์ฌ์ฉํด ์ฐ์ ์์์ ๋ง๋ ๋ฐ์ดํฐ๋ฅผ ๋ฝ์ ์ ์๋ ์๋ฃ๊ตฌ์กฐ์์ ๊ณต๋ถํ๋ค. (์๋ ํฌ์คํ ์ฐธ์กฐ)
โ๏ธ priority queue๋ ์ผ์ข ์ Abstract Data Structure(ADT)๋ก, ์ถ์ํ๋ ๊ฐ๋ ์ heap์ด๋ผ๋ ์๋ฃ๊ตฌ์กฐ๋ก implementํ ์ ์๋ค.
(์ฐ์ ์์๊ฐ ์ต๋ ๋จผ์ , ๋๋ ์ต์ ๋จผ์ ์ผ ๊ฒฝ์ฐ heap์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด ์ด์ ์ฐ์ ์์์ ๋ง๊ฒ ๊บผ๋ด์ค๋ค)
๐จ๐ซ ๋ฐ๋ผ์, ์ค์ ์๋ฃ๊ตฌ์กฐ heap์ ๋ํ ์์ธํ ๋ชจ๋ ์ ๋ณด๋ฅผ ์ ํํ ์ ๋ฆฌํด๋ด
๐จ๐ซ ์ผ๋จ heap data structure๋ ์ฌ๋ฌ ํํ๋ก ํํ๋ ์ ์๋ค. ์ด ์ค Binary heap์ ๋ํด ์์ธํ ์์๋ณด๋ ค ํ๋ค.
1. binary heap intro
๐จ๐ซ ๋ณดํต ์์์ ์ธ๊ธํ priority queue๋ฅผ ๊ตฌํํ ๋ ๋ง์ด ์ฐ์
๐จ๐ซ binary tree ํํ์ด๋ฉฐ, ๊ทธ ์ค complete binary tree ํํ๋ฅผ ๋ณด์ธ๋ค.
๐จ๐ซ binary tree๋ ๋ ๊ฐ์ ์กฐ๊ฑด ํ์ ์ ์๋๋ค. → shape property, heap property
* shape property - complete binary tree
๐จ๐ซ Complete Binary Tree(CBT; ์์ ์ด์ง ํธ๋ฆฌ)๋, root ๋ ธ๋๋ถํฐ ์์ํ์ฌ ์ผ์ชฝ ์์ ๋ ธ๋, ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋ ์์๋๋ก ๋ฐ์ดํฐ๊ฐ ์ฐจ๋ก๋๋ก ์ฝ์ ๋๋ tree๋ฅผ ๋ปํ๋ค.
'all levels of the tree, except possibly the last one (deepest) are fully filled, and, if the last level of the tree is not complete, the nodes of that level are filled from left to right.'
๐จ๐ซ ์ ๊ทธ๋ฆผ์ฒ๋ผ ์ผ์ชฝ๋ถํฐ ์ฐจ๋ก๋๋ก node์ ๋ฐ์ดํฐ๊ฐ ์ฑ์์ง๊ณ , ๋งจ ์๋์ธต์ ์ ์ธํ ๋ชจ๋ ์ธต์ node๊ฐ ์ฑ์์ง๋ค. ๋จ, ๋ง์ง๋ง ์ธต์ ์ผ์ชฝ๋ถํฐ node๊ฐ ์ฑ์์ง๋ค.
๐จ๐ซ Binary Tree ์ข ๋ฅ ํฌ์คํ ์ฐธ์กฐ
๐จ๐ซ ๋ฐ๋ผ์, ์๋ tree๋ค ์ค CBT๋ 1๋ฒ, 2๋ฒ, 5๋ฒ, 6๋ฒ์ด๋ค
๐จ๐ซ ๊ทธ๋ ๋ค๋ฉด, heap property์ ์ํด ๋๋๋, heap์ ๋ ์ข ๋ฅ max-heap๊ณผ min-heap์ ๋ํด ์์๋ณด์
* heap property - max-heap & min-heap
'Heap property: the key stored in each node is either greater than or equal to (≥) or less than or equal to (≤) the keys in the node's children, according to some total order.'
๐จ๐ซ max-heap: parent key๊ฐ child keys๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ heap
๐จ๐ซ min-heap: parent key๊ฐ child keys๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ heap
→ ๋ค์ ์ ๋ฆฌํ๋ฉด,
โ๏ธ ์ต์ heap(min-heap): root node๊ฐ ๊ฐ์ฅ ์์ ๊ฐ์ ๊ฐ์ง๋ฉฐ, ๊ฐ์ด ์์ ๋ฐ์ดํฐ๊ฐ ์ฐ์ ์ ์ผ๋ก ์ ๊ฑฐ๋๋ค.
(์ด๋ด ๊ฒฝ์ฐ ๋ง๋ค์ด์ง ์ต์ heap์ n๊ฐ์ ๋ฐ์ดํฐ๋ง ๋ฃ์ด๋ ์๋์ ์ผ๋ก ์ค๋ฆ์ฐจ์ ์ ๋ ฌ์ด ์์ฑ๋๋ค)
โ๏ธ ์ต๋ heap(max-heap): root node๊ฐ ๊ฐ์ฅ ํฐ ๊ฐ์ ๊ฐ์ง๋ฉฐ, ๊ฐ์ด ํฐ ๋ฐ์ดํฐ๊ฐ ์ฐ์ ์ ์ผ๋ก ์ ๊ฑฐ๋๋ค.
โป ๋ฐ๋ผ์, max-heap๊ณผ min-heap์ ์ฐ์ ์์ ํ๋ฅผ implementํ ๋, element๋ฅผ insertingํ๊ฑฐ๋, ๊ฐ์ฅ ์๊ฑฐ๋ ๊ฐ์ฅ ํฐ element๋ฅผ ๊ฐ๊ฐ min-heap๊ณผ max-heap์์ ๋นผ๋ ์ด ๋ ๊ฐ์ง operation์์ ํจ์จ์ ์ด๊ฒ ๋ง์ด ์ฐ์ธ๋ค.
โป ๋ํ, heapsort sorting algorithm(in-place algorithm)์ผ๋ก heap์ด ์ฐ์ธ๋ค. ์๋ก node๋ผ๋ฆฌ ์๋์ ์ผ๋ก ์์น๋ฅผ ๋ฐ๊พธ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ฏ๋ก in-place ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๐จ๐ซ ์์ (์ผ์ชฝ์ max-heap, ์ค๋ฅธ์ชฝ์ min-heap)
2. binary heap implementations
๐จ๐ซ heap ๊ตฌํ์linked list์ array ๋ ๊ตฌ์กฐ๋ก ๊ตฌํ์ด ๊ฐ๋ฅํ๋ฐ, linked list๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ ์ฐจ์ง,์ฃผ๋ก array๋ก ๊ตฌํ๋๋ค. array์ index๋ฅผ ์ด์ฉํด heap binary tree์ ์๋ ๊ณผ์ ์ ์์๋ณด์
* child & parent's node (based on the node's index)
โป ์์ node์ index๊ฐ i๋ผ๋ฉด
→ root node์ index๊ฐ 0์ด๋ฉด, ํ์ left node์ index๋ 2i+1, ํ์ right node์ index๋ 2i+2
→ root node์ index๊ฐ 1์ด๋ฉด, ํ์ left node์ index๋ 2i, ํ์ right node์ index๋ 2i+1
→ ์ array์๋ 10, 30, 40, 90, 60 ์์๋๋ก ๋ค์ด๊ฐ ์๋ค. root node๋ถํฐ ์ฐจ๋ก๋ก ์ผ์ชฝ๋ถํฐ array์ ๋ค์ด๊ฐ๋๋ฐ, ๋ง์ฝ ์์ node์ index๊ฐ x๋ผ๋ฉด
→ root node์ index๊ฐ 0์ผ ๊ฒฝ์ฐ parent node์ index๋ $\lfloor \cfrac{(x-1)}{2} \rfloor$
→ root node์ index๊ฐ 1์ผ ๊ฒฝ์ฐ parent node์ index๋ $\lfloor \cfrac{x}{2} \rfloor$)
๐จ๐ซ ์ฃผ์ด์ง array์ ์์๋ค์ array ๊ณต๊ฐ์ ๋ค์ ์จ์ ํด๋น ๊ณต๊ฐ์์ binary heap ํํ๋ก ์ ์ฅํ๋ heapsort ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ฐ์ธ๋ค.
๐จ๐ซ ์ ์์ฑ๋ binary heap๊ณผ array์์ index ์์, array element ์์๋ฅผ ์๋ก ์ ์ดํด๋ณด๋ฉฐ ๊ธฐ์ตํ์!
๐จ๐ซ heap์์ ์งํ๋๋ ์ฌ๋ฌ ๊ณผ์ ์ ์ผ๋จ max-heap์ ๊ธฐ์ค์ผ๋ก ํ๋ค.
* creating a heap
๐จ๐ซ ๊ทธ๋ ๋ค๋ฉด, heapsort์ core ์๊ณ ๋ฆฌ์ฆ์ธ, ์ฃผ์ด์ง array๋ฅผ binary heap ํํ๋ก ์ ์ฅํ๋ ๊ณผ์ ์ ํ ๋จ๊ณ์ฉ ์์ธํ ์ดํด๋ณด์
* ์์) array [33, 35, 42, 10, 7, 8, 14, 19, 48]์ด ์ฃผ์ด์ก๋ค๋ฉด, ๋งจ ์์ ์์๋ถํฐ ์์. child node๋ก ๋ค์ด๊ฐ ๋, parent node์ ํฌ๊ธฐ๋ฅผ ๋น๊ตํ๊ณ , max-heap์ผ ๊ฒฝ์ฐ, parent node๋ณด๋ค ๋ค์ด๊ฐ๋ ์์๊ฐ ๋ ํฌ๋ค๋ฉด ์๋ก swap. ๋ค์ ์์ parent node์ ๋น๊ต (min-heap์ parent node๋ณด๋ค ์์๊ฐ ๋ ์๋ค๋ฉด parent node์ swap)
- ๊ทธ ๊ฒฐ๊ณผ array [48, 42, 35, 33, 7, 8, 14, 10, 19]์ธ binary max-heap ์์ฑ
- ์์ฑ๋ binary max-heap -
๐จ๐ซ ์ ์์ A [33, 35, 42, 10, 7, 8, 14, 19, 48]๊ฐ ์ฃผ์ด์ก์ ๋, ์ฃผ์ด์ง array๋ฅผ binary heap์ ๋ง๊ฒ ๋ฐ๊พธ๋ heapify๋ฅผ python์ผ๋ก ๊ตฌํ!
→ ์ถ๋ ฅํ๋ฉด A๊ฐ [48, 35, 42, 33, 7, 8, 14, 19, 10]๋ก ๋ฐ๋๋ค.
def heapify(arr, n, parent_idx):
largest = parent_idx
left = parent_idx*2 + 1
right = parent_idx*2 + 2
if left < n and arr[left] > arr[largest]:
largest = left
if right < n and arr[right] > arr[largest]:
largest = right
if largest != parent_idx: #if changed
arr[largest], arr[parent_idx] = arr[parent_idx], arr[largest] #swap
heapify(arr, n, largest) #if swapped, continue with the lower part
arr = [33, 35, 42, 10, 7, 8, 14, 19, 48]
for i in range((len(arr)-1)//2,-1,-1): #heapify
heapify(arr, len(arr), i)
print(arr)
print(arr) #[48, 35, 42, 33, 7, 8, 14, 19, 10]
→ heapfiy() ์๊ฐ ๋ณต์ก๋ O(N) (๊ฐ node๋ณ heapify()๋ฅผ ์ฌ๋ฌ ๋ฒ ์ํ)
โถ time complexity โ
→ ๋จผ์ , ์ด n๊ฐ์ node๊ฐ ์๋ค๊ณ ํ๊ณ , ๋ฐ๋ฅ๋ถํฐ h=0, ๊ทธ ๋ค์ ์ธต h=1๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์งํ๋๋ค๊ณ ๊ฐ์ ํ๋ฉด, h๋ผ๋ ์ธต์ ์กด์ฌํ๋ ์ต๋ node ๊ฐ์๋ $\cfrac{n}{2^{h+1}}$
→ last non-leaf node๋ถํฐ root-node๊น์ง ๊ฐ๊ฐ max_heapify()๊ฐ ์งํ๋๋ค. ์ด ๋, max_heapify()์์ swap์ ์ํ comparison ํ์๋ ๊ณง ์์ node์ height๋ฅผ ๋ปํ๋ค. ๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ ์๊ฐ๋ณต์ก๋๋ฅผ h๋ผ๋ ์ธต์์ $O(h) * \lceil\cfrac{n}{2^{h+1}}\rceil$๋ก ๋ํ๋ผ ์ ์๋ค.
(O(h)๋ ์์ node์ height - ์ฆ ์ผ์ ์์ $c*h$๋ก ํํ ๊ฐ๋ฅ)
→ ๊ฐ ๋ชจ๋ ์ธต์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ตฌํ๋ฉด, n๊ฐ์ node์์ ์ธต์ ๊ฐ์๋ logn์ด๋ฏ๋ก $\sum_{0}^{log n}O(h) * \lceil\cfrac{n}{2^{h+1}}\rceil$
= $\cfrac{n*c}{2} \sum_{0}^{logn} \lceil\cfrac{n}{2^h}\rceil$
→ logn์ ∞๋ก ๋ฐ๊พธ๋ฉด, harmonic progression์ ์ํด ์๊ทธ๋ง๊ฐ์ 2๊ฐ ๋๋ค.
= $\cfrac{n*c}{2} * 2$ = $c*n$
โถ T(n) = O(n) โ
โป ์๋ ์ฐธ์กฐ โป
* deleting from heap → heapsort
๐จ๐ซ ์ด๋ฏธ ์์ฑ๋ binary heap์์ ํ ์์๋ฅผ deleteํ ๋ค๋ ๊ฒ์, ๊ฐ์ฅ ์์์ root node๋ฅผ ๋นผ ์จ๋ค๋ ๋ป์ด๊ณ , max-heap์ผ ๊ฒฝ์ฐ ์์์ ์ต๋๊ฐ, min-heap์ผ ๊ฒฝ์ฐ ์์์ ์ต์๊ฐ์ ๊ฐ์ ธ์ค๊ฒ ๋๋ค.
๐จ๐ซ root- node๋ฅผ ๋นผ์ค๊ณ ๋จ์ ์๋ฆฌ์๋, bottom-most right-most element๋ฅผ ๋นผ์จ๋ค. (array๊ตฌ์กฐ์ index๊ฐ ๊ฐ์ฅ ํฐ, ๋งจ ์ค๋ฅธ์ชฝ์ ์์). ์ด๋ฅผ root node์ ์ฌ๋ ค๋๋๋ค.
*์์) ์ ์์๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฉด, 42๋ฅผ ๋นผ๊ณ , 10 ์์๋ฅผ ๋งจ ์์ ์ฌ๋ ค ๋๋๋ค. ์ด ๋, ํญ์ max-heap ๊ตฌ์กฐ๋ฅผ ์ ์งํด์ผ ํ๋ฏ๋ก, ์๋ก ๋ฐ๋ root-node์ child-node๋ฅผ ๋น๊ตํ๋ค. swap์ด ์งํ๋๋ฉด, ์ดํ ์๋ ๋ถ๋ถ๊น์ง ๋์ ๊ด๊ณ๊ฐ max-heap ๊ตฌ์กฐ์ ๋ง์ง ์์ผ๋ฉด ๊ณ์ํด์ swap ์งํ
- (์ข) root node ๋นผ์ค๊ณ ๋ง์ง๋ง ์์๋ฅผ root node๋ก ์ฌ๋ฆผ / (์ฐ) ์ต์ข ์ ์ผ๋ก swap ๊ณผ์ ์ด ์งํ๋ ํ ๋ค์ ์ ๋ฐ์ดํธ ๋ max-heap -
- update๋ max-heap์ array ํํ๋ก ํํํ๋ฉด [35, 33, 14, 19, 7, 8, 10]์ด ๋๋ค.
- ์ด์ ๊ฐ์ด ๊ณ์ํด์ root-node deletion์ ์งํํ๋ฉด ์ ์ผ ํฐ ์๋ถํฐ ์ฐจ๋ก๋๋ก delete๋๋ค. ๋ฐ๋ผ์, delete๋ ์์๋ฅผ ์ฐจ๋ก๋๋ก ๋ชจ์ผ๋ฉด, sort๋ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค. ์ด sorting์ heapsort๋ผ๊ณ ๋ถ๋ฅธ๋ค.
(์ฌ๊ธฐ์ parent node์ ๋ child node ์ค ์ ์ผ ํฐ child์ swap์ด ์งํ๋๋ค.
left์ swap์ดํ right์ ํ ๋ฒ ๋ swap์ด ์งํ๋๋ ๊ฒ ์๋)
- ์๋ ์ฝ๋ heapsort ์ฐธ์กฐ -
def max_heap(arr, n, parent_idx):
largest = parent_idx
left = parent_idx*2 + 1
right = parent_idx*2 + 2
if left < n and arr[left] > arr[largest]:
largest = left
if right < n and arr[right] > arr[largest]:
largest = right
if largest != parent_idx: #if changed
arr[largest], arr[parent_idx] = arr[parent_idx], arr[largest] #swap
max_heap(arr, n, largest) #if swapped, continue with the lower part
def heapsort(arr):
n = len(arr)
for i in range((n-1)//2,-1,-1): #first heapify
max_heap(arr, n, i)
for i in range(n-1,0,-1): #heapsort (until last single element remained)
arr[i], arr[0] = arr[0], arr[i] #swap with the last and the first(max) element
max_heap(arr,i,0) #after swapped, heapify (start with the first element)
arr = [33, 35, 42, 10, 7, 8, 14, 19, 48]
heapsort(arr)
print(arr) #[7, 8, 10, 14, 19, 33, 35, 42, 48]
โ max_heap(): arr์ ์ ์ฒด arr ๊ธธ์ด, ํ์ฌ parent_idx ์ธ ๊ฐ์ ์ธ์
→ ์ผ๋จ ํ์ฌ largest index๋ parent_idx์ด๊ณ , ์์ node์ index๋ parent_index*2 +1๊ณผ parent_index*2+2
(IndexError ๊ฑฑ์ ํ ํ์ ์๋ค. max_heap์ ๋๋ฆด ๋ non-leaf node ๊น์ง๋ง ๋๋ฆฌ๊ธฐ ๋๋ฌธ)
→ ์์ left node๊ฐ parent node๋ณด๋ค ํฌ๋ค๋ฉด, ๊ทธ๋ฆฌ๊ณ left node์ index๊ฐ n๋ณด๋ค ์๋ค๋ฉด, swap ํ์ํ๋ฏ๋ก index swap
→ ์ดํ ์์ right node์๋ ๋์ผํ๊ฒ ์งํ
→ ๋ง์ฝ index swap์ด ์งํ๋์๋ค๋ฉด(largest != parent_idx)
- arr[largest]์ arr[parent_idx]์์ swap ์งํ
- ๊ทธ๋ฆฌ๊ณ , ์ดํ ์๋ ํ์ ๋ ธ๋์๋ ์ด๋ฅผ ๋ฐ๋ณตํด์ผ ํ๋ฏ๋ก max_heap(arr, n, largest) ์งํ
(์ด ๋, parent_idx๋ largest์ด๋ฏ๋ก, largest๋ฅผ ์ธ์๋ก ๋ฃ์)
→ heapify() ์๊ฐ ๋ณต์ก๋ O(logN)
โก heapsort()
→ last non-leaf node๋ถํฐ(์ฆ, n๊ฐ์ node์์ index๊ฐ $\lfloor \cfrac{n}{2} - 1 \rfloor$์ธ node๋ถํฐ) root node๊น์ง ์ฐจ๋ก๋๋ก heapify() ์ ๊ฒ
(last non-leaf node๋, ์์ ๋ ธ๋๊ฐ 1๊ฐ ์ด์ ์๋ node ์ค index๊ฐ ์ ์ผ ํฐ, ์ฆ array์์ ๋งจ ๋์ ์๋ node๋ฅผ ๋ปํ๋ค. ์ฆ ์์์ด ์๋ ๋ ๋ ธ๋๋ถํฐ root node๊น์ง max-heap ๊ตฌํ์ ์ํด swap ์ฌ๋ถ๋ฅผ ์์๊ณผ ๊ณ์ ์ค์ํ๋ค๋ ๋ป) - for loop ๋๋ฆผ
→ ํ ๋ฒ์ heapify() ์งํ ํ, n๋ฒ์ heapify() ์งํ (for loop ๋๋ฆผ) - ์ฒซ๋ฒ์งธ ์์์ ๋งจ ๋ง์ง๋ง ์์ swap & max_heap() ๋๋ ค heapify() ์งํ
(ํ ๊ฐ ๋จ์ ๋ ๊น์ง ์งํํ๋ฏ๋ก, index n-1๋ถํฐ 1๊น์ง)
โถ heapsort T(n) = O(nlogn) โ
→ ๊ฐ๊ฐ max node๋ฅผ ๋นผ์ค๊ณ ๋งค ๋ฒ heapify()๋ฅผ ์งํํด์ฃผ๋ฏ๋ก, heapify()์ ์๊ฐ ๋ณต์ก๋๋ O(logn)์ธ ์ํ์์, max node๋ฅผ ๋นผ์ค๋ ํ์ n์ด ์ต์ข ์ ์ผ๋ก ๊ณฑํด์ ธ O(nlogn)์ ์๊ฐ๋ณต์ก๋๊ฐ ๋๋ค.
* inserting key into heap
๐จ๐ซ ์ด๋ฏธ ์์ฑ๋ heap์์ ๋งจ ๋ง์ง๋ง์ ์๋ก์ด ์์๋ฅผ insertionํ ์ ์๋ค. ์ด ๋, max-heap์ ์ฑ์ง์ ์ ์งํ๊ธฐ ์ํด ๋ถ๋ชจ ๋ ธ๋ ์์์ ๊ณ์ ๋น๊ตํ๋ฉฐ ์์๋ก ์ฌ๋ผ๊ฐ๋ค. (ํ๋จ ๊ทธ๋ฆผ ์ฐธ์กฐ)
๐จ๐ซ ์ด์ฒ๋ผ, ์์์ binary heap ์์ ์ค ํ ๊ฐ์ ๊ฐ์ ๋ฐ๊พผ๋ค๋ฉด, ์์ ๋ ธ๋์ ๊ณ์ ๋น๊ตํ๋ฉด์ max-heap ์์ฑ์ ์ํด swap ๊ณผ์ ์ด ์งํ๋ ์ ์๋ค.
โป binary heap ํน์ฑ์ ์์ node์ index๊ฐ i๋ผ๋ฉด, ๋ถ๋ชจ node์ index๋ i/2 โป
def insert_key(arr,key):
arr.append(key)
size=len(arr)
i=size
while(i>=1 and arr[i/2] < arr[i]):
arr[i],arr[i/2] = arr[i/2],arr[i] #swap
i = (i/2)
print(arr)
โถ T(n) = O(h) = O(logn) โ
(node์ ๊ฐ์ ์ฆ๊ฐ์์ผ heap์ updateํ๋ ์ฐ์ฐ์ ์๊ฐ ๋ณต์ก๋๋ ์์ node๊ฐ ์ต๋ ๋ถ๋ชจ node๊น์ง ์์ง์ด๋, ์ฆ heap์ height๊ฐ ๋๋ฏ๋ก, ์ด๋ ๊ณง logn)
* extract max from heap
๐จ๐ซ ์ง๊ธ max-heap์ ๋ค๋ฃจ๊ณ ์์ผ๋ฏ๋ก, heap์ ์์ ์ค ์ต๋๊ฐ์ ๊ฐ์ฅ ์์ ๋ ธ๋์ ์๋ ๊ฐ์ด๋ค. ๋ฐ๋ผ์ ๋งจ ์์ ๋ ธ๋๋ฅผ ๋นผ๊ณ , ๊ทธ ์๋ฆฌ์ ๊ฐ์ฅ ๋์ ์๋ ์์๋ฅผ ๊ฐ๋ค ์ค๋ค. (ํ๋จ ๊ทธ๋ฆผ ์ฐธ์กฐ)
def delete_max(arr):
size=len(arr)
if size < 1:
print('Error')
max_root = arr[0]
arr[0] = arr[size]
size=size-1
A=max_heapify(arr[:size],1)
return max_root
๐จ๐ซ max๊ฐ์ ๋ฐํํ๊ณ , ๋ง์ง๋ง ์์๋ฅผ root node๋ก ์ฌ๋ฆฐ ๋ค, max_heapify()๋ฅผ ์ฌ์ฉํด max-heap์ผ๋ก ๋ค์ ๋ง๋ ๋ค.
โถ T(n) = O(logn) โ
(max_root๋ฅผ ์ต์์ node์์ ๊บผ๋ด๋ ๊ฑด O(1), max_heapify()๋ O(logn)์ผ๋ก ์ต์ข O(logn))
* increase key in heap
๐จ๐ซ ์์) ๋งจ ๋ง์ง๋ง rightmost node ๊ฐ์ 60์ผ๋ก ๋ฐ๊พผ๋ค๋ฉด max-heap ์ฑ์ง์ ์ํด ์์ ๋ ธ๋ 42์ ๋น๊ตํด์ swap, ์ดํ ์์ ๋ ธ๋ 48๊ณผ ๋น๊ตํด์ swap ์งํ (์๋ ๊ทธ๋ฆผ ์ฐธ์กฐ)
๐จ๐ซ ์ด์ฒ๋ผ, ์์์ binary heap ์์ ์ค ํ ๊ฐ์ ๊ฐ์ ๋ฐ๊พผ๋ค๋ฉด, ์์ ๋ ธ๋์ ๊ณ์ ๋น๊ตํ๋ฉด์ max-heap ์์ฑ์ ์ํด swap ๊ณผ์ ์ด ์งํ๋ ์ ์๋ค.
โป binary heap ํน์ฑ์ ์์ node์ index๊ฐ i๋ผ๋ฉด, ๋ถ๋ชจ node์ index๋ i/2 โป
def increase_key(arr,i,key):
if key < arr[i]:
print('Error')
arr[i] = key
while(i>=1 and arr[i/2] < arr[i]):
arr[i],arr[i/2] = arr[i/2],arr[i] #swap
i = (i/2)
print(arr)
โถ T(n) = O(h) = logn / S(n) = 1โ
→ node์ ๊ฐ์ ์ฆ๊ฐ์์ผ heap์ updateํ๋ ์ฐ์ฐ์ ์๊ฐ ๋ณต์ก๋๋ ์์ node๊ฐ ์ต๋ ๋ถ๋ชจ node๊น์ง ์์ง์ด๋, ์ฆ heap์ height๊ฐ ๋๋ฏ๋ก, ์ด๋ ๊ณง logn / ๊ณต๊ฐ๋ณต์ก๋๋ ํ์ฌ ๊ณต๊ฐ์์ recursion์ด ์ผ์ด๋์ง ์์ผ๋ฏ๋ก ๊ทธ๋๋ก 1
3. binary heap time complexity
๐จ๐ซ ์ ์ฌ๋ฌ implementation ์ฐ์ฐ time complexity๋ฅผ ์ ๋ฆฌํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
operation | ์๊ฐ ๋ณต์ก๋ |
find max(root node ์ ๊ทผ) | O(1) |
heapify() (creating a heap) | O(n) |
heapsort() | O(nlogn) |
insertion | O(logn) |
deletion / extracting max | O(logn) |
increasing value in a heap | O(logn) |
4. binary heap code using heapq in python
๐จ๐ซ python์์ heapq๋ผ๋ library๋ฅผ ์ง์ํด์ฃผ์ด heap ์ฌ๋ฌ implementation์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
๐จ๐ซ heapq docu
๐จ๐ซ python์ heapq๋ default๋ก min-heap์ ๊ตฌํํ๋ค.
Q. heapsort using min-heap
import sys
import heapq
input=sys.stdin.readline
def heapsort(iterable):
h=[]
res=[]
#๋ชจ๋ ์์๋ฅผ ์ฐจ๋ก๋๋ก heap์ ์ฝ์
for value in iterable:
heapq.heappush(h,value)
#heap์ ์ฝ์
๋ ๋ชจ๋ ์์๋ฅผ ์ฐจ๋ก๋๋ก ๊บผ๋ด์ด ๋ด๊ธฐ
for i in range(len(h)):
res.append(heapq.heappop(h))
return res
n=int(input())
arr=[]
for i in range(n):
arr.append(int(input()))
res=heapsort(arr)
for i in range(n):
print(res[i])
1) heapq์ heappush์ ์ํด min-heap ์์ฑ
2) min-heap์ด๋ฏ๋ก heapq์ heappop์ ์ํด ๊ฐ์ฅ ๋ง์ง๋ง node๊ฐ root node์ ์ค๋ฉด์ root node์ธ ์ต์๊ฐ์ด ์ถ๋ ฅ
3) ์ 2)์ ๊ณผ์ ์ ๊ณ์ ๋ฐ๋ณตํ๋ฉด์ ์ถ๋ ฅ๋๋ ๊ฐ์ ๋์ดํ๋ฉด ์ค๋ฆ์ฐจ์ ์ ๋ ฌ!
→ ์๋ฅผ ์ฐจ๋ก๋๋ก ์ง์ด๋ฃ์ผ๋ฉด, ์ค๋ฆ์ฐจ์ ์ ๋ ฌ๋๋ก ์ถ๋ ฅ๋์ด ๋์จ๋ค.
โป python์ ๊ฒฝ์ฐ heapq๋ min-heap ์ต์ ํ์ ๊ตฌํํด์ฃผ๋ library๋ค. ๋ฐ๋ผ์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ๋๋ค โป
Q. heapsort using max-heap
โป max-heap์ python์ ๊ฒฝ์ฐ ์ min-heap ๊ตฌํ ์ฝ๋์ heappush ์ฌ์ฉ์ value์ ์์๋ฅผ ๋ถ์ฌ heap์ ์ง์ด๋ฃ๊ณ , ์ ๋ ฌํ ๋ค, heappop ์ฌ์ฉํ ๋ ๋ค์ ์์๋ฅผ ๋ถ์ด๋ฉด ๋๋ค.
import sys
import heapq
input=sys.stdin.readline
def heapsort(iterable):
h=[]
res=[]
#๋ชจ๋ ์์๋ฅผ ์ฐจ๋ก๋๋ก heap์ ์ฝ์
for value in iterable:
heapq.heappush(h,-value)
#heap์ ์ฝ์
๋ ๋ชจ๋ ์์๋ฅผ ์ฐจ๋ก๋๋ก ๊บผ๋ด์ด ๋ด๊ธฐ
for i in range(len(h)):
res.append(-heapq.heappop(h))
return res
n=int(input())
arr=[]
for i in range(n):
arr.append(int(input()))
res=heapsort(arr)
for i in range(n):
print(res[i])
Q. building a heap - heapify()
→ min-heap(์์ ์ด์ง ํธ๋ฆฌ)์ ์ค์ ๋ก ๋ง๋๋ heapify()๋ O(n)์ ์๊ฐ ๋ณต์ก๋.
import heapq
nums = [9,7,5,3,1]
heapq.heapify(nums)
print(nums) #[1,3,5,9,7]
Q. deletion using heappop() - find the nth smallest
โ ์ ๋ง๋ค์ด์ง heap [1,3,5,9,7]์์
โก ์๋ฅผ ๋ค์ด ์ธ ๋ฒ์งธ ์์ ์์๋ฅผ ์ฐพ๊ณ ์ถ๋ค๋ฉด ์ด ๋ ๋ฒ์ heappop() ์ํํ ๋ค O(1)์ด ๊ฑธ๋ฆฌ๋ nums[0] ์ฐ์ฐ ์ํ
heapq.heappop(nums)
print(nums) #[3,7,5,9]
heapq.heappop(nums)
print(nums) #[5,7,9]
print(nums[0]) #5
#heap์ node ์ถ๋ ฅ
→ ์ธ ๋ฒ์งธ ์์ ์์ 5 ์ถ๋ ฅ!
* heap youtube https://youtu.be/TK48r1Dlo4k
* binary heap wiki https://en.wikipedia.org/wiki/Binary_heap
* ์ธ๋ค์ผ ์ถ์ฒ https://www.digitalocean.com/community/tutorials/max-heap-java
'Computer Science > Data Structures' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ณ Binary Tree ๐ณ (1) | 2023.12.19 |
---|---|
set() & dict() - ์งํฉ๊ณผ ๋งต (0) | 2023.08.03 |
Types of Binary Tree๐ฒ (0) | 2023.01.10 |
priority queue(binary heap) (0) | 2023.01.09 |
hash table / hashing (0) | 2022.11.06 |
๋๊ธ