힙(Heap)
완전 이진트리의 자료구조로 값의 최대 힙과 최소 힙의 유형을 가지고 있습니다.
삽입, 삭제의 시간복잡도는 O(log N)을 가지고 있습니다.
힙 정렬
주어진 데이터를 힙(Heap)을 사용하여 정렬하는 알고리즘입니다.
- 최대 힙(Max Heap) : 내림차순 정렬
- 최소 힙(Min Heap) : 오름차순 정렬
힙 정렬 과정
1. 리스트의 원소들을 모두 힙에 넣는다.
2. 힙의 루트 원소를 뽑아 정렬시킬 배열에 놓고 힙에서는 제거한다.
3. 2번의 과정을 재귀적으로 오름차순 또는 내림차순으로 정렬될때까지 반복한다.
특징 및 장단점
- 제자리 정렬 (In-Place Sorting) : 추가적인 메모리 공간을 필요로 하지 않으며, 주어진 배열에서 바로 정렬을 수행한다.
- 데이터를 비교하며 정렬을 수행한다.
- 최선,평균,최악의 시간 복잡도는 O(log n)으로 일정한 시간복잡도를 보장한다.
- 정렬하는 원소가 동일한 값일 경우, 순서를 보장하지 않는다.
힙정렬 구현
// Heap (완전 이진 트리 형태)
// 정렬할 배열 , 배열의 크기, 루트가 될 원소
void heapify(int arr[], int n, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
// (right < n && arr[left] < arr[smallest]) -> 최소 힙
if (left < n && arr[left] > arr[largest])
{
largest = left;
}
// (right < n && arr[right] < arr[smallest] -> 최소 힙
if (right < n && arr[right] > arr[largest])
{
largest = right;
}
if (largest != i) {
std::swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
// 힙정렬
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--)
{
std::swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
병합 정렬 (Merge Sort)
- 리스트의 원소들을 재귀적으로 반으로 나누고, 각 부분들을 정렬한 후 병합(Merge) 과정을 통해 다시 합치는 방식
- 분할정복 알고리즘
- 두 개의 정렬된 리스트를 합쳐서 하나의 정렬된 리스트로 만드는 과정
특징 및 장단점
- 분할정복 알고리즘
- 동일한 값에대한 순서를 보장한다.
- 리스트를 분할하고 병합하는 단계에서 병렬 처리에 유용하다.
- 최선,최악,평균 시간복잡도 O(n lon n)을 유지한다.
- 정렬시 추가적인 메모리 공간이 O(n)만큼 필요하다.
병합정렬 구현
// 병합
void merge(std::vector<int>& arr, int left, int right)
{
if (left >= right) return;
int mid = left + (right - left) / 2;
merge(arr, left, mid);
merge(arr, mid + 1, right);
// 병합 단계
int n1 = mid - left + 1; // 왼쪽 크기
int n2 = right - mid; // 오른쪽 크기
// 임시배열. 공간복잡도 O(n)이 추가적으로 필요한 이유
std::vector<int> leftArr(n1), rightArr(n2);
// 값 복사
for (int i = 0; i < n1; i++)
{
leftArr[i] = arr[left + i];
}
for (int i = 0; i < n2; i++)
{
rightArr[i] = arr[mid + 1 + i];
}
// 두 배열 병합
int i = 0, j = 0, k = left;
while (i < n1 && j < n2)
{
if (leftArr[i] <= rightArr[j])
{
arr[k] = leftArr[i];
i++;
}
else
{
arr[k] = rightArr[j];
j++;
}
k++;
}
// 왼쪽 배열의 나머지 항목 복사
while (i < n1)
{
arr[k] = leftArr[i];
i++;
k++;
}
// 오른쪽 배열의 나머지 항목 복사
while (j < n2)
{
arr[k] = rightArr[j];
j++;
k++;
}
}
// 병합정렬 (분할)
void mergeSort(std::vector<int>& arr, int left, int right) {
if (left < right)
{
int mid = left + (right - left) / 2; // 중간값 계산
mergeSort(arr, left, mid); // 왼쪽 절반
mergeSort(arr, mid + 1, right); // 나머지 오른쪽 절반
merge(arr, left, right); // 마지막 병합
}
}
'알고리즘 , 자료구조' 카테고리의 다른 글
[알고리즘] Graph - 깊이 우선 탐색 DFS (Depth First Search) (0) | 2025.01.17 |
---|---|
[알고리즘] 해시 테이블 (Hash Table) (0) | 2025.01.16 |
[알고리즘] 레드블랙 트리 , RBT (Red-Black Tree) (0) | 2025.01.10 |
[알고리즘] 이진탐색트리 BST(Binary Search Tree) (0) | 2025.01.09 |
[자료구조] 트리 (Tree) (0) | 2025.01.08 |