Notice
Recent Posts
Recent Comments
Link
Β«   2025/01   Β»
일 μ›” ν™” 수 λͺ© 금 ν† 
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

DOing

[자료ꡬ쑰] μš°μ„ μˆœμœ„ 큐, νž™ λ³Έλ¬Έ

μ•Œκ³ λ¦¬μ¦˜

[자료ꡬ쑰] μš°μ„ μˆœμœ„ 큐, νž™

mangdo 2021. 5. 19. 09:31

πŸ’‘ μš°μ„ μˆœμœ„ 큐?

일반적인 νλŠ” First-In-First-Outκ΅¬μ‘°μ΄μ§€λ§Œ,

μš°μ„ μˆœμœ„ 큐(Priority Queue)λŠ” μš°μ„ μˆœμœ„κ°€ 높은 데이터가 λ¨Όμ €λ‚˜μ˜€λŠ” ꡬ쑰이닀.

μš°μ„ μˆœμœ„ 큐λ₯Ό λ°°μ—΄μ΄λ‚˜ μ—°κ²°λ¦¬μŠ€νŠΈλ‘œ κ΅¬ν˜„ν•  μ‹œμ—λŠ” μš°μ„ μˆœμœ„μ— 맞게 데이터λ₯Ό μ‚½μž…ν•˜λŠ” μ‹œκ°„μ΄ 였래걸리게 λœλ‹€.

λ•Œλ¬Έμ— μš°μ„ μˆœμœ„ νλŠ” νž™μ„ μ΄μš©ν•΄μ„œ κ΅¬ν˜„ν•œλ‹€.


πŸ’‘ νž™?

νž™μ€ μ΅œλŒ€κ°’κ³Ό μ΅œμ†Œκ°’μ„ λΉ λ₯΄κ²Œ μ°ΎκΈ° μœ„ν•΄ κ³ μ•ˆλœ μ™„μ „μ΄μ§„νŠΈλ¦¬μ΄λ‹€.

(=λ³€ν˜•λœ 트리의 ν˜•νƒœ)

 

[ νž™μ˜ ꡬ쑰 ]

: μ΅œλŒ€κ°’μ„ κ΅¬ν•˜κΈ° μœ„ν•œ ꡬ쑰인 μ΅œλŒ€νž™κ³Ό μ΅œμ†Œκ°’μ„ κ΅¬ν•˜κΈ° μœ„ν•œ ꡬ쑰인 μ΅œμ†Œνž™μ΄ μžˆλ‹€.

νž™μ€ λ‹€μŒκ³Ό 같이 두가지 쑰건을 가지고 μžˆλŠ” μžλ£Œκ΅¬μ‘°μ΄λ‹€. (μ΅œλŒ€νž™ κΈ°μ€€)

1) λΆ€λͺ¨λ…Έλ“œλŠ” μžμ‹λ…Έλ“œμ˜ 값보닀 ν¬κ±°λ‚˜ κ°™λ‹€.

2) μ™„μ „ 이진 νŠΈλ¦¬ν˜•νƒœ

 

μ΅œμ†Œνž™κ³Ό μ΅œλŒ€νž™

 

[ νž™κ³Ό 이진 탐색 트리 비ꡐ ]

* 곡톡점 : μ΄μ§„νŠΈλ¦¬λ‹€.

* 차이점 :

- νž™μ€ 각 λ…Έλ“œμ˜ 값이 μžμ‹λ…Έλ“œλ³΄λ‹€ ν¬κ±°λ‚˜ κ°™λ‹€.

- 이진 탐색 νŠΈλ¦¬λŠ” μ™Όμͺ½ μžμ‹λ…Έλ“œμ˜ 값이 κ°€μž₯ μž‘κ³ , λΆ€λͺ¨λ…Έλ“œ, 였λ₯Έμͺ½ μžμ‹λ…Έλ“œ μˆœμ΄λ‹€.

- νž™μ€ μ™Όμͺ½ μžμ‹μ΄ 클지 였λ₯Έμͺ½ μžμ‹μ΄ ν΄μ§€λŠ” λͺ¨λ₯Έλ‹€.

* λͺ©μ  : 이진 탐색 νŠΈλ¦¬λŠ” 탐색을 μœ„ν•œ ꡬ쑰, νž™μ€ μ΅œλŒ€/μ΅œμ†Œκ°’ 검색을 μœ„ν•œ ꡬ쑰닀.

 

 

πŸ’‘ νž™μ˜ λ™μž‘

[ 데이터 μ‚½μž… ]

1. μ™„μ „ μ΄μ§„νŠΈλ¦¬λ‘œ λ§Œλ“ λ‹€.

: λΆ€λͺ¨λ…Έλ“œλ³΄λ‹€ 크더라도 일단은, μ™„μ „ μ΄μ§„νŠΈλ¦¬λ‘œ λ§Œλ“€κ³  μ‹œμž‘ν•œλ‹€. κ·Έλž˜μ„œ μ™Όμͺ½ μ΅œν•˜λ‹¨λΆ€ λ…Έλ“œλΆ€ν„° μ±„μš΄λ‹€.

2.  μžμ‹λ…Έλ“œκ°€ λΆ€λͺ¨λ…Έλ“œλ³΄λ‹€ 크닀면 λ°”κΏ”μ€€λ‹€.

: 20κ³Ό 8을 λ°”κΎΈκ³ , 20κ³Ό 15와 λ°”κΏ”μ€€λ‹€. 루트 λ…Έλ“œκ°€ λ λ•ŒκΉŒμ§€ 쑰건을 체크해쀀닀.

[ 데이터 μ‚­μ œ ]

1. 루트 λ…Έλ“œλ₯Ό μ‚­μ œν•œλ‹€.(=μ΅œλŒ€κ°’μ„ 뽑아낸닀)

2. μ΅œν•˜λ‹¨λΆ€μ˜ λ…Έλ“œλ₯Ό 루트둜 μ„€μ •ν•œλ‹€.

 3. μžμ‹λ…Έλ“œκ°€ λΆ€λͺ¨λ³΄λ‹€ 크닀면, μžμ‹λ…Έλ“œ λ‘˜ 쀑 더 큰 κ°’κ³Ό λ°”κΎΌλ‹€.

: 15κ°€ 10보닀 크기 λ•Œλ¬Έμ— 15와 8을 λ°”κΎΌλ‹€. μžμ‹λ…Έλ“œκ°€ μ—†μ„λ•ŒκΉŒμ§€ 이λ₯Ό λ°˜λ³΅ν•œλ‹€.

πŸ’‘ νž™μ˜ κ΅¬ν˜„(with Python)

더보기
class Heap:
    def __init__(self, data):
        self.heap_array = list()
        self.heap_array.append(None) # 1λΆ€ν„° μ‹œμž‘ν•  μ˜ˆμ •
        self.heap_array.append(data)

    # λ£¨νŠΈλ…Έλ“œκ°€ μžμ‹λ…Έλ“œλž‘ μœ„μΉ˜λ₯Ό λ³€κ²½ν•΄μ•Όν•˜λŠ”κ°€λ₯Ό νŒλ‹¨
    def move_down(self, popped_idx):
        left_child_popped_idx = popped_idx * 2
        right_child_popped_idx = popped_idx * 2 + 1

        # case1: μ™Όμͺ½ μžμ‹ λ…Έλ“œλ„ 없을 λ•Œ
        if left_child_popped_idx >= len(self.heap_array):
            return False
        # case2: 였λ₯Έμͺ½ μžμ‹ λ…Έλ“œλ§Œ 없을 λ•Œ (μ™„μ „μ΄μ§„νŠΈλ¦¬λΌλŠ” 것을 μœ μ˜ν•˜μž)
        elif right_child_popped_idx >= len(self.heap_array):
            if self.heap_array[popped_idx] < self.heap_array[left_child_popped_idx]:
                return True # μžμ‹λ…Έλ“œκ°€ 더 ν¬λ‹ˆκΉŒ λ°”κΏ”μ€˜μ•Όν•¨
            else:
                return False
        # case3: μ™Όμͺ½, 였λ₯Έμͺ½ μžμ‹ λ…Έλ“œ λͺ¨λ‘ μžˆμ„ λ•Œ
        else:
            # μžμ‹λ…Έλ“œλΌλ¦¬ 비ꡐ
            if self.heap_array[left_child_popped_idx] > self.heap_array[right_child_popped_idx]:
                if self.heap_array[popped_idx] < self.heap_array[left_child_popped_idx]:
                    return True # μžμ‹λ…Έλ“œκ°€ 더 크닀면 λ°”κΏ”μ€˜μ•Όν•¨
                else:
                    return False
            else:
                if self.heap_array[popped_idx] < self.heap_array[right_child_popped_idx]:
                    return True # μžμ‹λ…Έλ“œκ°€ 더 크닀면 λ°”κΏ”μ€˜μ•Όν•¨
                else:
                    return False

    def pop(self):
        if len(self.heap_array) <= 1:
            return None

        returned_data = self.heap_array[1]
        self.heap_array[1] = self.heap_array[-1] # λ£¨νŠΈλ…Έλ“œλ₯Ό μ΅œν•˜λ‹¨ λ…Έλ“œλ‘œ λ³€κ²½
        del self.heap_array[-1]
        popped_idx = 1

        while self.move_down(popped_idx):
            left_child_popped_idx = popped_idx * 2
            right_child_popped_idx = popped_idx * 2 + 1

            # case2: 였λ₯Έμͺ½ μžμ‹ λ…Έλ“œλ§Œ 없을 λ•Œ
            if right_child_popped_idx >= len(self.heap_array):
                if self.heap_array[popped_idx] < self.heap_array[left_child_popped_idx]:
                    self.heap_array[popped_idx], self.heap_array[left_child_popped_idx] = self.heap_array[left_child_popped_idx], self.heap_array[popped_idx]
                    popped_idx = left_child_popped_idx

            # case3: μ™Όμͺ½, 였λ₯Έμͺ½ μžμ‹ λ…Έλ“œ λͺ¨λ‘ μžˆμ„ λ•Œ
            else:
                # μžμ‹λ…Έλ“œλΌλ¦¬ 비ꡐ
                if self.heap_array[left_child_popped_idx] > self.heap_array[right_child_popped_idx]:
                    if self.heap_array[popped_idx] < self.heap_array[left_child_popped_idx]:
                        self.heap_array[popped_idx], self.heap_array[left_child_popped_idx] = self.heap_array[left_child_popped_idx], self.heap_array[popped_idx]
                        popped_idx = left_child_popped_idx
                else:
                    if self.heap_array[popped_idx] < self.heap_array[right_child_popped_idx]:
                        self.heap_array[popped_idx], self.heap_array[right_child_popped_idx] = self.heap_array[right_child_popped_idx], self.heap_array[popped_idx]
                        popped_idx = right_child_popped_idx

        return returned_data

    # ν˜„μž¬ λ…Έλ“œκ°€ μƒμœ„λ…Έλ“œμ™€ λ°”κΏ”μ•Όν•˜λŠ”μ§€λ₯Ό νŒλ‹¨
    def move_up(self, inserted_idx):
        if inserted_idx <= 1: # λ£¨νŠΈλ…Έλ“œλ©΄ λ°”κΏ€ λ…Έλ“œκ°€ μ—†λ‹€.
            return False
        parent_idx = inserted_idx // 2
        if self.heap_array[inserted_idx] > self.heap_array[parent_idx]:
            return True
        else:
            return False

    def insert(self, data):
        if len(self.heap_array) == 1: # λ°©μ–΄μ½”λ“œ
            self.heap_array.append(data)
            return True

        self.heap_array.append(data) # 일단 μ™„μ „ μ΄μ§„νŠΈλ¦¬λ‘œ λ§Œλ“ λ‹€
        inserted_idx = len(self.heap_array) - 1

        while self.move_up(inserted_idx): # ν˜„μž¬λ…Έλ“œλ₯Ό μƒμœ„λ…Έλ“œμ™€ λ°”κΏ”μ•Όν•œλ‹€κ³  νŒλ‹¨ν–ˆλ‹€λ©΄
            parent_idx = inserted_idx // 2
            self.heap_array[inserted_idx], self.heap_array[parent_idx] = self.heap_array[parent_idx], self.heap_array[inserted_idx]
            inserted_idx = parent_idx
        return True

heap = Heap(15)
heap.insert(10)
heap.insert(20)
heap.insert(11)

print(heap.heap_array) # 확인 [None,20,15,11,10]
print(heap.pop()) # 20
print(heap.heap_array) # 확인 [None,15,11,10]

 

 

πŸ’‘ νž™μ˜ μ‹œκ°„λ³΅μž‘λ„

μš°μ„  μ΅œλŒ€ λ…Έλ“œμ˜ κ°œμˆ˜κ°€ N이라면, 트리의 높이 h = \( log_{2}(N+1)-1 \)이닀.

μ‚½μž… μ‚­μ œμ‹œ, μ΅œμ•…μ˜ κ²½μš°μ—λŠ” rootλ…Έλ“œμ—μ„œ leaf λ…Έλ“œκΉŒμ§€ λΉ„κ΅ν•΄μ•Όν•¨μœΌλ‘œ O(logn)의 μ‹œκ°„ λ³΅μž‘λ„λ₯Ό 가진닀.

λ‹¨μˆœ λ°°μ—΄μ—μ„œ μ΅œλŒ€/μ΅œμ†Œκ°’μ„ 찾으렀면 O(n)의 μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ°€μ§€λŠ” 것에 λΉ„ν•˜λ©΄ 훨씬 λΉ λ₯Έ μ†λ„λ‘œ μ΅œλŒ€/μ΅œμ†Œκ°’μ„ 찾을 수 μžˆλ‹€.

 

πŸ’‘ νŒŒμ΄μ¬μ—μ„œ νž™ μ‚¬μš©ν•˜κΈ°

* μ΅œμ†Œνž™

import heapq

# μ΅œμ†Œνž™
minHeap = []
heapq.heappush(minHeap, 2)
heapq.heappush(minHeap, 3)
heapq.heappush(minHeap, 1)

# μ΅œμ†Œκ°’ 좜λ ₯
while minHeap:
    print(heapq.heappop(minHeap), end=" ")

 

* μ΅œλŒ€νž™

: 파이썬 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œλŠ” 기본적으둜 μ΅œμ†Œνž™λ§Œ μ œκ³΅ν•˜κ³  μžˆλ‹€.

λ•Œλ¬Έμ— μ΅œμ†Œνž™μ„ μ΅œλŒ€νž™μ²˜λŸΌ μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œ μš°μ„ μˆœμœ„μ— ν•΄λ‹Ήν•˜λŠ” 값에 음수 λΆ€ν˜Έ(-)λ₯Ό λΆ™μ—¬μ„œ λ„£μ—ˆλ‹€κ°€, κΊΌλ‚Όλ•Œμ— λ‹€μ‹œ 음수 λΆ€ν˜Έ(-)λ₯Ό λΆ™μ—¬μ„œ μ›λž˜μ˜ κ°’μœΌλ‘œ λŒλ¦¬λŠ” 방식을 μ‚¬μš©ν•  수 μžˆλ‹€.

 

import heapq

# μ΅œλŒ€νž™
maxHeap = []
heapq.heappush(maxHeap, -2)
heapq.heappush(maxHeap, -3)
heapq.heappush(maxHeap, -1)

# μ΅œλŒ“κ°’ 좜λ ₯
while maxHeap:
    print(-heapq.heappop(maxHeap), end=" ")

 

 

 

 

좜처

슀파λ₯΄νƒ€ μ½”λ”©ν΄λŸ½ μ•Œκ³ λ¦¬μ¦˜ κ°•μ˜

패슀트캠퍼슀 μ•Œκ³ λ¦¬μ¦˜ κ°•μ˜