[Algorithm] 힙(heap) 이란?
in Algorithm on DataStructure, Heap
1. 자료구조 힙(Heap)이란?
- 완전 이진 트리의 일종으로 우선순위 큐를 위하여 만들어진 자료구조이다.
- 여러 개의 값들 중에서 최댓값이나 최솟값을 빠르게 찾아내도록 만들어진 자료구조이다.
- 힙은 일종의 반 정렬 상태(느슨한 정렬 상태)를 유지한다.
- 큰 값이 상위 레벨에 있고 작은 값이 하위 레벨에 있다는 정도
- 간단히 말하면 부모 노드의 키 값이 자식 노드의 키 값보다 항상 큰(작은)이진 트리를 말한다.
- 힙 트리에서는 중복된 값을 허용한다. (이진 탐색 트리에서는 중복된 값을 허용하지 않는다.)
2 .힙의 종류
- 최대 힙(max heap)
- 부모 노드의 키 값이 자식 노드의 키 값보다 크거나 같은 완전 이진 트리
- key(부모 노드) >= key(자식 노드)
- 최소 힙(min heap)
- 부모 노드의 키 값이 자식 노드의 키 값보다 작거나 같은 완전 이진 트리
- key(부모 노드) <= key(자식 노드)
3. 힙(heap) 구현
- 힙을 저장하는 표준적인 자료구조는 배열이다
- 구현을 쉽게 하기 위하여 배열의 첫 번째 인덱스인 0은 사용되지 않는다.
- 특정 위치의 노드 번호는 새로운 노드가 추가되어도 변하지 않는다.
- 예를 들어 루트 노드의 오른쪽 노드의 번호는 항상 3이다.
- 힙에서의 부모 노드와 자식 노드의 관계
- 왼쪽 자식의 인덱스 = (부모의 인덱스) * 2
- 오른쪽 자식의 인덱스 = (부모의 인덱스) * 2 + 1
4. 힙(heap) 삽입
- 합에 새로운 요소가 들어오면, 일단 새로운 노드를 힙의 마지막 노드에 이어서 삽입한다.
- 새로운 노드를 부모 노드들과 교환해서 힙의 성질을 만족시킨다.
- 아래의 최대 힙(max heap)에 새로운 요소 8을 삽입
5. 힙(heap)의 삭제
- 최대 힙에서 최댓값은 루트 노드이므로 루트 노드가 삭제된다.
- 최대 힙(max heap)에서 삭제 연산은 최댓값을 가진 요소를 삭제하는 것이다.
- 삭제된 루트 노드에는 힙의 마지막 노드를 가져온다.
- 힙을 재구성한다.
- 아래의 최대 힙(max heap)에서 최댓값을 삭제해보자.
Python에서의 힙
Python은 heapq모듈을 통해 heapq를 제공합니다. minheap으로 구현되어 있어 가장 앞에 있는 원소가 가장 작은 원소입니다.
heapq - heapify
- heapq 모듈의 heapify 함수는 주어진 리스트를 힙 정렬합니다. 이때의 Time Complexity는 O(nlongn)입니다.
# 힙 정렬 예시
import heapq
my_list = [13, 2, 1, 5, 10]
heapq.heapify(my_list)
# 가장 작은 원소인 1이 가장 앞으로 왔습니다.
my_list # [1, 2, 13, 5, 10]
heap - heappop(heap)
- heap모듈의 heappop 함수는 힙 정렬된 리스트에서
- 가장 작은 원소를 빼내고
- 나머지 원소가 힙을 유지하도록 정리합니다.
- 이 함수를 사용할 때에는 주어진 리스트가 힙 정렬되어 있는지 반드시 확인해야 합니다.
- 정렬되지 않은 리스트에 heappop을 사용하면 이상한 결과가 나옵니다.
import heapq
my_list = [13, 2, 1, 5, 10]
heapq.heapify(my_list)
# 가장 작은 원소인 1이 리턴됩니다. my_list의 길이가 하나 줄어듭니다.
ret_val = heapq.heappop(my_list)
print("리턴된 값:", ret_val) # 1
print("남은 원소:", my_list) # [2, 5, 13, 10]
heap - heappush(heap, item)
- heap모듈의 heappush 함수는 힙 정렬된 리스트의 힙 상태를 유지하면서 데이터를 삽입시켜줍니다.
- 이 함수를 사용할 때에는 주어진 리스트가 힙 정렬되어있는지 반드시 확인해야 합니다.
- 정렬되지 않은 리스트에 heappush를 사용하면 이상한 결과가 나옵니다.
import heapq
my_list = [13, 2, 1, 5, 10]
heapq.heapify(my_list)
# -1 삽입
heapq.heappush(my_list, -1)
# 가장 작은 원소인 -1이 가장 앞에 위치
print("남은 원소:", my_list) # [-1, 2, 1, 5, 10, 13]
Reference
https://gmlwjd9405.github.io/2018/05/10/data-structure-heap.html