반응형
📖 합병 정렬(Merge Sort)이란?
합병 정렬은 비교 기반의 분할 정복 알고리즘의 하나이며 안정 정렬에 속합니다.
합병 정렬의 과정은 퀵 정렬과 비슷하며 퀵 정렬의 경우 피벗 값에 따라 편향되게 분할할 가능성이 있다는 점에서 최악의 경우 O(n²)의 시간 복잡도를 가집니다. 하지만 합병 정렬의 경우 일반적인 경우 퀵 정렬보단 느리지만 피벗 값이 없고 반절씩 나눈다는 점에서 최악의 경우에도 O(nlogn)의 시간 복잡도를 보장합니다.
n-way 합병 정렬 (일반적으로 하향식 2-way 방식을 사용)
- 정렬되지 않은 리스트를 각각 하나의 원소만 포함하는 n개의 부분 리스트로 분할한다. (한 원소만 든 리스트는 정렬된 것과 같으므로)
- 부분 리스트가 하나만 남을 때까지 반복해서 병합하며 정렬된 부분 리스트를 생성한다. 마지막 남은 부분 리스트가 정렬된 리스트이다.
🔎 합병 정렬의 특징
- 시간 복잡도는 데이터의 분포에 상관없이 항상 O(nlogn)을 고정
- 배열의 요소가 1개가 될 때까지 분할 -> n번 호출
- 배열을 반씩 분할해가며 정렬 -> logn 만큼 호출
- 안정 정렬
- 데이터가 배열로 구성된 경우 추가적인 임시 배열 필요
- 데이터 크기가 큰 경우 비효율적
🗝️ GIF로 보는 합병 정렬 알고리즘
- 분할(divide) : 정렬되지 않은 리스트를 절반으로 잘라 비슷한 크기의 두 부분 리스트로 나눈다.
- 정복(conquer) : 각 부분 리스트를 재귀적으로 합병 정렬을 이용해 정렬한다.
- 결합(combine) : 두 부분 리스트를 다시 하나의 정렬된 리스트로 합병한다. 이때 정렬 결과가 임시 배열에 저장된다.
- 복사(copy) : 임시 배열에 저장된 결과를 원래 배열에 복사한다.
👨🏻💻 JAVA로 구현
package ex_packege;
import java.util.*;
public class Main {
public static int tmp[] = new int[8];
public static void merge(int arr[], int left, int mid, int right) {
int i, j, k;
i = left; // 정렬된 왼쪽 리스트에 대한 인덱스
j = mid + 1; // 정렬된 오른쪽 리스트에 대한 인덱스
k = left; // 정렬될 리스트에 대한 인덱스
// 분할 정렬된 list의 합병
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
tmp[k++] = arr[i++];
} else {
tmp[k++] = arr[j++];
}
}
// 남아있는 값 넣기
if (i > mid) {
for (int l = j; l <= right; l++) {
tmp[k++] = arr[l];
}
} else {// (j > right)
for (int l = i; l <= mid; l++) {
tmp[k++] = arr[l];
}
}
// 임시배열 tmp를 arr로 복사
for (int l = left; l <= right; l++) {
arr[l] = tmp[l];
}
}
public static void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int arr[] = { 6, 5, 3, 1, 8, 7, 2, 4 };
mergeSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
📚 참고
https://blog.naver.com/ndb796/221227934987
https://ko.wikipedia.org/wiki/%ED%95%A9%EB%B3%91_%EC%A0%95%EB%A0%AC
https://gmlwjd9405.github.io/2018/05/08/algorithm-merge-sort.html
반응형
'🗝️Algorithm' 카테고리의 다른 글
[Algorithm] 퀵 정렬(Quick Sort)이란? (0) | 2021.11.23 |
---|---|
[Algorithm] 삽입 정렬(Insertion Sort)이란? (0) | 2021.11.17 |
[Algorithm] 최장 증가 부분 수열(LIS) 알고리즘 (JAVA로 구현) (0) | 2021.10.27 |
[Algorithm] 선택 정렬(Selection Sort) 이란? (0) | 2021.10.17 |
[Algorithm] 순열(Permutation)과 조합(Combination) JAVA로 구현하기 (순열, 중복순열, 조합, 중복조합) (0) | 2021.10.17 |