#요약
- 현대 컴퓨터의 아버지 '존 폰 노이만'이 제안
- 분할 정복(Divid & Conquer)의 전략을 도입
- 문제를 작은 문제로 분리하고 각각 해결한 후에, 결과를 모아서 원래 문제를 해결하는 전략
- 순환 호출을 구현
- 리스트의 길이가 0 OR 1일때 이미 정렬된 것
- 정렬되지 않는 리스트들 절반으로 잘바 비슷한 크기의 두 부분 리스트로 나눔 ➡️ Divid
- 각 부분 리스트를 재귀적으로 병합 정렬을 이용해 정렬 ➡️ Conquer
- 두 부분 리스트를 다시 하나의 정렬된 리스트로 병합 ➡️ Combine
#구체적 설명
- 하나의 데이터 배열을 균등하게 절반으로 나눈다.
- 나누어진 2개의 배열을 정렬한다.
- 분할: 입력 배열을 2개의 부분 배열로 분할한다.
- 정복: 부분 배열을 정렬한다. 부분 배열의 크기가 충분히 작지 않을때 다시 분할한다.
- 결합: 분할되어 정렬된 데이터들을 합친다.
- 이 과정을 반복한다.
#알고리즘
#코드 작성
public class main
{
static int[] arr = new int[]{7,5,2,4,0,3,6,1};
public static void main(String[] args)
{
mergeSort(arr,0 ,arr.length);
for(int i = 0 ; i < arr.length ; i++){
System.out.printf("%d ", arr[i]);
}
}
static void mergeSort(int[] arr,int low,int high){
if (high - low < 2) { //0,1 까지 분할
return;
}
int mid = (low + high) / 2;
mergeSort(arr, 0, mid); //재귀로 분할
mergeSort(arr, mid, high); //재귀로 분할
merge(arr, low, mid, high); //병합
}
//병합함수
static void merge(int list[], int low, int mid, int high){
int[] temp = new int[high - low]; //복사하기 위한 함수 생성
int t = 0, l = low, h = mid;
while (l < mid && h < high) {
if (arr[l] < arr[h]) {
temp[t++] = arr[l++];
} else {
temp[t++] = arr[h++];
}
}
while (l < mid) {
temp[t++] = arr[l++];
}
while (h < high) {
temp[t++] = arr[h++];
}
for (int i = low; i < high; i++) {
arr[i] = temp[i - low];
}
}
}
#결과
0 1 2 3 4 5 6 7
#시간복잡도
최선 | O(nlogn) |
평균 | O(nlogn) |
최악 | O(nlogn) |
#장단점
장점 | 단점 |
- 최선, 최악, 평균이 모두 O(nlogn) 으로 동일하다. - 제자리 정렬중 선택 정렬, 삽입 정렬 보다 효율적이다. |
- 데이터를 저장하기 위한 추가적인 저장공간이 필요하다. - 데이터가 크기가 큰 경우 이동횟수가 많으므로 시간 비 |
※ 분할 정복(Divid & Conquer) 전략
- 가장 유명한 알고리즘 디자인 패러다임
- 큰 문제를 작은 문제로 쪼개서 해결하는 기법
- 주어진 문제를 둘 이상의 부분 문제로 나누고 각 문제를 해결
- 선형적인 방법보다 빠르게 문제를 해결 가능
반응형
'Algorithm > Concept' 카테고리의 다른 글
[DP] LIS(최장 증가 부분 수열) (0) | 2024.05.21 |
---|---|
[Algorithm] 정렬 - 힙정렬(Heap Sort) (0) | 2023.11.22 |
[Algorithm] 정렬 - 삽입 정렬(Insertion Sort) (0) | 2023.11.13 |
[Algorithm] 정렬 - 선택 정렬(Selection Sort) (0) | 2023.11.13 |
[Algorithm] 정렬 - 칵테일 정렬(Cocktail Sort) (0) | 2023.11.11 |