-
패스트 캠퍼스 챌린지 25일차 - 자료구조 힙#4카테고리 없음 2021. 9. 30. 19:37
목차
- Heap의 pop
- Heap의 구현(pop)
- 시간 복잡도
1.Heap의 Insert
- 보통 삭제는 최상단 노드 (root 노드)를 삭제하는 것이 일반적임
- 힙의 용도는 최대값 또는 최소값을 root 노드에 놓아서, 최대값과 최소값을 바로 꺼내 쓸 수 있도록 하는 것임
- 상단의 데이터 삭제시, 가장 최하단부 왼쪽에 위치한 노드 (일반적으로 가장 마지막에 추가한 노드) 를 root 노드로 이동
- root 노드의 값이 child node 보다 작을 경우, root 노드의 child node 중 가장 큰 값을 가진 노드와 root 노드 위치를 바꿔주는 작업을 반복함 (swap)
- 특정 노드의 관련 노드 위치 알아내기
- 부모 노드 인덱스 번호 (parent node's index) = 자식 노드 인덱스 번호 (child node's index) // 2
- 왼쪽 자식 노드 인덱스 번호 (left child node's index) = 부모 노드 인덱스 번호 (parent node's index) * 2
- 오른쪽 자식 노드 인덱스 번호 (right child node's index) = 부모 노드 인덱스 번호 (parent node's index) * 2+1
2.Heap의 구현(pop)
class Heap: def __init__(self, data): self.heap_array = list() self.heap_array.append(None) 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
3.시간복잡도
- depth (트리의 높이) 를 h라고 표기한다면,
- n개의 노드를 가지는 heap 에 데이터 삽입 또는 삭제시, 최악의 경우 root 노드에서 leaf 노드까지 비교해야 하므로 h=log2n 에 가까우므로, 시간 복잡도는 O(logn)
- 참고: 빅오 표기법에서 logn 에서의 log의 밑은 10이 아니라, 2입니다.
- 한번 실행시마다, 50%의 실행할 수도 있는 명령을 제거한다는 의미. 즉 50%의 실행시간을 단축시킬 수 있다는 것을 의미함