힙정렬(Heap Sort)은 선택 정렬의 한 종류로, 최대 힙(또는 최소 힙) 자료구조를 이용하여 정렬하는 알고리즘이다.
힙정렬은 항상 n logn 이다.
Heap이란?
트리 기반의 데이터 구조로 완전 이진 트리이다.
최대 힙 (Max Heap): 부모 노드의 값이 자식 노드의 값보다 크거나 같다. 루트 노드는 항상 최대 값을 가진다.
최소 힙 (Min Heap): 부모 노드의 값이 자식 노드의 값보다 작거나 같다. 루트 노드는 항상 최소 값을 가진다.
최소힙 예 1
/ \
3 5
/ \ / \
4 8 6 9
기본적인 동작 방식
- 주어진 배열을 최대 힙(또는 최소 힙) 구조로 만든다. 이는 부모 노드가 자식 노드들보다 크거나(최대 힙) 작은(최소 힙) 구조를 갖도록 조정하는 과정이고 이를 힙화(Heapify)라고 한다.
- 최상단 노드(루트 노드)를 배열의 가장 마지막 요소와 교환한다. 이로써 가장 큰(또는 가장 작은) 요소가 배열의 마지막에 위치하게 된다.
- 힙 크기를 하나 줄이고(마지막 요소를 힙에서 제외시킴) 다시 최대 힙(또는 최소 힙) 속성을 만족하도록 힙을 조정한다.
- 위 과정을 반복하여 전체 배열이 정렬될 때까지 진행한다.
public class HeapSort {
// 힙 정렬 알고리즘
public static void heapSort(int[] arr) {
int n = arr.length;
// 힙 구성 (배열 재배열)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
// 힙에서 하나씩 요소 추출
for (int i = n - 1; i > 0; i--) {
// 현재 루트를 끝으로 이동
swap(arr, 0, i);
// 축소된 힙에서 힙 정렬 재귀 호출
heapify(arr, i, 0);
}
}
// 배열의 인덱스 i를 루트로 하는 서브트리를 힙으로 만드는 함수
static void heapify(int[] arr, int n, int i) {
int largest = i; // 현재 루트를 가장 큰 값으로 초기화
int left = 2 * i + 1; // 왼쪽 자식 노드 인덱스: 2*i + 1
int right = 2 * i + 2; // 오른쪽 자식 노드 인덱스: 2*i + 2
// 왼쪽 자식이 현재 루트보다 크면 largest를 왼쪽 자식으로 변경
if (left < n && arr[left] > arr[largest])
largest = left;
// 오른쪽 자식이 현재 largest보다 크면 largest를 오른쪽 자식으로 변경
if (right < n && arr[right] > arr[largest])
largest = right;
// largest가 현재 루트가 아니라면 교환 후 재귀적으로 힙 구성
if (largest != i) {
swap(arr, i, largest);
// 영향을 받은 서브트리에 대해 재귀적으로 heapify 호출
heapify(arr, n, largest);
}
}
// 배열의 두 요소를 교환하는 swap 메서드
static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
728x90
'자료구조 & 알고리즘' 카테고리의 다른 글
Priority Queue & Heap (0) | 2024.08.12 |
---|---|
해시 함수와 알고리즘 (0) | 2024.08.05 |
Kadane: 배열에서 최대 연속 부분 배열 합 구하기 (0) | 2024.03.13 |
오일러 피 (0) | 2024.03.03 |
기수 정렬 (0) | 2024.03.01 |