어서와 자료구조와 알고리즘은 처음이지? 의 강의를 듣고 작성된 글입니다.
출처 : https://kakunblog.tistory.com/11
힙에는 최대 힙(max heap)과, 최소 힙(min heap)이 있다. 원소의 순서 기준이 내림차순이냐, 오름차순이냐에 따라 달라지고 완전히 대칭이다.
루트 노드가 항상 최댓값을 가진다.
완전 이진 트리이다. 때문에 노드의 추가와 삭제는 배열의 맨 마지막 원소에서만 일어난다.
최대 힙 내의 임의의 노드를 루트로 하는 서브 트리또한 최대 힙이다.
log(n) + 1
로 정해진다.log(n)
에 비례한다.log(n)
이다.class MaxHeap:
def __init__(self):
self.data = [None]
def insert(self, item):
self.data.append(item)
index = len(self.data) -1 # 마지막 인덱스
while index != 1:
parentNode = index // 2
'''
마지막 인덱스의 값이 부모 노드보다 크다면 위치를 바꾸어준다.
인덱스에 부모 노드의 값을 넣어 인덱스가 1이 아닐때까지 반복한다.
'''
if self.data[parentNode] < self.data[index]:
self.data[parentNode], self.data[index] = self.data[index], self.data[parentNode]
index = parentNode
else:
break
def remove(self):
# 힙이 비어있지 않을때
if len(self.data) > 1:
# 루트노드와 마지막 노드의 위치를 바꾸어 준다
self.data[1], self.data[-1] = self.data[-1], self.data[1]
# 마지막 노드를 지워준다
data = self.data.pop(-1)
else:
data = None
return data
def maxHeapify(self, i):
# 왼쪽 자식의 인덱스 계산
left = i * 2
# 오른쪽 자식의 인덱스 계산
right = i * 2 + 1
# 작은 값의 인덱스를 가지는 값으로 초기화
smallest = i
# 왼쪽 자식이 존재하면 왼쪽 자식의 키 값이 무엇보다 더 큰지를 판단
if left < len(self.data) and self.data[left] > self.data[smallest]:
# 조건이 만족한다면 smallest는 왼쪽 자식의 인덱스로 교체된다.
smallest = left
# 오른쪽 자식이 존재하면 오른쪽 자식의 키 값이 무엇보다 더 큰지를 판단
if right < len(self.data) and self.data[right] > self.data[smallest]:
# 조건이 만족한다면 smallest는 오른쪽 자식의 인덱스로 교체된다.
smallest = right
if smallest != i:
# 현재 노드와 최댓값 노드(왼쪽 혹은 오른쪽 자식)를 교체한다
self.data[smallest], self.data[i] = self.data[i], self.data[smallest]
# 재귀적 호출을 통해 최대 힙의 성지를 만족할때까지 트리를 정렬한다.
self.maxHeapify(smallest)
우선 순위 큐(priority queue)
느슨한 정렬
을 이루고 있도록 함 O(log n)힙 정렬(heap sort)
def heapSort(unsorted):
H = MaxHeap()
for item in unsorted:
H.insert(item)
sorted = []
# 정렬되지 않은 값들이 정렬된다.
d = H.remove()
while d:
sorted.append(d)
d = H.remove()
return sorted