힙 정렬
힙 정렬은 비교 기반 정렬 알고리즘입니다. 알고리즘에 사용 된 힙 데이터 구조에서 이름을 가져옵니다. 힙은 이진 트리 기반 특수 데이터 구조입니다. 다음과 같은 두 가지 속성이 있습니다.
- 마지막 레벨을 제외한 모든 레벨이 채워진 완전한 이진 트리입니다. 마지막 노드는 부분적으로 채워질 수 있지만 모든 노드는 가능한 한 왼쪽에 있습니다.
- 모든 부모 노드는 두 자식 노드보다 작거나 큽니다. 더 작 으면 힙을 최소 힙이라고하고 더 크면 힙을 최대 힙이라고합니다. 주어진 인덱스
i
에 대해 부모는(i-1) / 2
로, 왼쪽 자식은(2 * i + 1)
로, 오른쪽 자식은(2 * i +2)
.
힙 정렬은 선택 정렬과 매우 유사한 방식으로 작동합니다. max-heap을 사용하여 배열에서 최대 요소를 선택하고 배열 뒷면의 해당 위치에 배치합니다. 힙을 빌드하기 위해heapify()
라는 절차를 사용합니다.
힙 정렬 알고리즘
n
요소를 포함하는 정렬되지 않은 배열A[]
가 있다고 가정 해 보겠습니다.
HeapSort()
-
배열
A
내부에 요소가있는 최대 힙을 빌드합니다. -
A
의 마지막 요소부터 시작하는 모든 요소에 대해 다음을 수행합니다. -
루트 요소
A[0]
에는 최대 요소가 포함되며이 요소로 교체합니다. -
힙 크기를 1로 줄이고 마지막 요소가 제거 된 최대 힙을
Heapify()
로 줄입니다.
Heapify()
-
현재 요소의 인덱스로
parent
인덱스를 초기화합니다. -
leftChild
를2 * i + 1
로,rightChild
를2 * i + 2
로 계산합니다. -
leftChild
의 요소가parent
인덱스의 값보다 크면parent
인덱스를leftChild
로 설정하십시오. -
rightChild
의 요소가parent
색인의 값보다 크면parent
색인을rightChild
로 설정하십시오. -
마지막 두 단계에서
parent
인덱스의 값이 변경된 경우 부모를 현재 요소로 바꾸고parent
인덱스 하위 트리를 재귀 적으로heapify
합니다. 그렇지 않으면 힙 속성이 이미 충족됩니다.
힙 정렬 예
배열이(5, 3, 4, 2, 1, 6)
이라고 가정합니다. 힙 정렬 알고리즘을 사용하여 정렬합니다.
힙을 빌드 한 후 배열을(6 3 5 2 1 4)
로 얻습니다.
- 첫 번째 반복 :
Swap(A[5],A[0]) |
4 3 5 2 1 6 |
Heapify() |
5 3 4 2 1 6 |
- 두 번째 반복 :
Swap(A[4],A[0]) |
1 3 4 2 5 6 |
Heapify() |
4 3 1 2 5 6 |
- 세 번째 반복 :
Swap(A[3],A[0]) |
2 3 1 4 5 6 |
Heapify() |
3 2 1 4 5 6 |
- 네 번째 반복 :
Swap(A[2],A[0]) |
1 2 3 4 5 6 |
Heapify() |
2 1 3 4 5 6 |
- 다섯 번째 반복 :
Swap(A[1],A[0]) |
1 2 3 4 5 6 |
Heapify() |
1 2 3 4 5 6 |
- 여섯 번째 반복 :
Swap(A[0],A[0]) |
1 2 3 4 5 6 |
Heapify() |
1 2 3 4 5 6 |
정렬 된 배열은(1,2,3,4,5,6)
로 얻습니다.
힙 정렬 알고리즘 구현
#include <bits/stdc++.h>
using namespace std;
void heapify(int arr[], int n, int i) {
int parent = i;
int leftChild = 2 * i + 1;
int rightChild = 2 * i + 2;
if (leftChild < n && arr[leftChild] > arr[parent]) parent = leftChild;
if (rightChild < n && arr[rightChild] > arr[parent]) parent = rightChild;
if (parent != i) {
swap(arr[i], arr[parent]);
heapify(arr, n, parent);
}
}
void heapSort(int arr[], int n) {
for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--) {
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
int main() {
int n = 6;
int arr[6] = {5, 3, 4, 2, 1, 6};
cout << "Input array: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << "\n";
heapSort(arr, n); // Sort elements in ascending order
cout << "Output array: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << "\n";
}
힙 정렬 알고리즘 복잡성
시간 복잡성
- 평균 사례
n
요소가있는 완전한 이진 트리의 높이는 최대logn
입니다. 따라서heapify()
함수는 요소가 루트에서 리프로 이동할 때 최대logn
비교를 가질 수 있습니다. 빌드 힙 함수는n/2
요소에 대해 호출되어 첫 번째 단계n/2*logn
또는T(n)
=nlogn
의 총 시간 복잡도를 만듭니다.
HeapSort()
는 각 요소에 대해logn
최악의 시간이 걸리며n
요소는 시간 복잡도를nlogn
으로 만듭니다. 힙 및 힙 정렬을 빌드하기위한 시간 복잡성이 모두 추가되어 결과 복잡성을 nlogn
으로 제공합니다. 따라서 총 시간 복잡도는 [Big Theta] :O(nlogn)
의 순서입니다.
- 최악의 경우
최악의 시간 복잡도는 [Big O] :O(nlogn)
입니다.
- 베스트 케이스
최적의 시간 복잡도는 [Big Omega] :O(nlogn)
입니다. 최악의 시간 복잡성과 동일합니다.
공간 복잡성
힙 정렬 알고리즘의 공간 복잡성은 임시 변수 이외의 추가 메모리가 필요하지 않기 때문에O(1)
입니다.
Harshit Jindal has done his Bachelors in Computer Science Engineering(2021) from DTU. He has always been a problem solver and now turned that into his profession. Currently working at M365 Cloud Security team(Torus) on Cloud Security Services and Datacenter Buildout Automation.
LinkedIn