완전 이진 트리에 있는 노드 중에서 key 값이 가장 큰 노드나 key 값이 가장 작은 노드를 찾기 위해서 만든 자료구조
- 키 값이 가장 큰 노드를 찾기 위한
완전 이진 트리 - 부모노드의 key값 > 자식노드의 key값
- 루트 노드 : key 값이 가장 큰 노드
- 키 값이 가장 작은 노드를 찾기 위한
완전 이진 트리 - 부모노드의 key값 < 자식노드의 key값
- 루트 노드 : key 값이 가장 작은 노드
알고리즘
최대 힙에 값을 추가하고 배치를 바꾸는 알고리즘
''' 최대 100개의 정수 최대 heap ''' def enq(n): global last last += 1 # 마지막 정점 인덱스 증가 tree[last] = n # 완전이진트리 유지를 위해 last 인덱스에 값 추가(정점 추가) c = last # 새로 추가된 정점을 자식으로 p = c//2 # 완전이진트리에서의 부모 정점 번호 while p > 0 and tree[p] < tree[c]: # 부모 노드가 있고 자식의 키 값이 더 크면 교환 tree[p], tree[c] = tree[c], tree[p] # 값을 교환 c = p # 원래 부모였던 키값을 자식 키값으로 두기 위해 c에 저장 p = c//2 # 이 자식 키값으로부터 부모 키값 계산해 p에 저장 -> 위의 부모자식 확인 # 포화 이진트리의 정점번호 1~100 tree = [0] * 101 last = 0 enq(3) enq(2) enq(4) enq(7) enq(5) enq(1) print(tree[1]) # 1번 노드의 값(최댓값)을 출력
결과
7
알고리즘
최대 힙에 루트인 최댓값을 반환하고 삭제해 재배치하는 알고리즘
def deq(): global last ret = tree[1] # 1. root의 값을 ret에 저장, 이게 반환값 tree[1] = tree[last] # 2. 마지막 정점의 key 값을 root에 복사 last -= 1 # 3. 마지막 정점 인덱스 감소 : 즉 마지막 정점 삭제 처리 # 부모 > 자식 규칙 유지 p, c = 1, 2 # 최초 루트를 부모로 하고, 왼쪽 자식 조회 while c <= last: # 왼쪽 자식이 있으면 오른쪽 자식까지 고려해서 큰 자식이랑 계속 교환 # 1. 오른쪽 자식이 있고, 오른쪽 자식이 더 크면 if c+1<=last and tree[c] < tree[c+1]: c += 1 # 오른쪽 자식 선택 # 2. 자식의 값이 더 크면 교환 if tree[p] < tree[c]: # 값 교환 tree[p], tree[c] = tree[c], tree[p] p = c # 부모 노드였던 것이 자식으로 내려오고, c = p * 2 # 새 자식 노드 키 계산해서 또 확인 반복 # 3. 부모의 값이 더 큰 경우 탈출 else: break # pop했던 최대값 반환 -> 삭제 이후 루트에는 최댓값이 다시 배치 return ret while last > 0: print(deq(), tree[1])
- deq()를 호출
- root 노드(최댓값) 반환
- 다음 최댓값은 tree[1]으로 이동
- heap 관련 함수들을 가지는 모듈
- heappop(arr)
- heap arr의 val을 오름차순으로 pop해준다.
- heappush(arr, val)
- heap arr에 val을 추가해준다.
- heapify(arr)
- arr을 heap으로 바꿔준다.
