반응형
MergeSort?
- 대표적인 분할정복 정렬 알고리즘 중의 하나
cf> 분할정복(Divide And Conquer) ? : 문제를 작은 2개의 문제로 분리하여, 해결하고 결과를 합치는 전략이다.
- 메모리를 잡아먹는 특징 때문에, 안정성이 많이 보장되는 정렬 알고리즘이다.
- 시간복잡도는 O(NlogN), 공간복잡도는 O(N) 이다.
++ 배열을 1개로 될 때까지 각각을 n/2로 줄이니 당연히 logN 이다.
++ 합칠 때는 총 N번의 비교연산이 들어가므로 N*logN 이 되는 시간복잡도이다!
- 보통 정렬의 공간복잡도는 O(1)인데, 병합정렬의 경우 복사할 배열이 새로 필요하다!
언제 써야될까?
1. 많은 데이터를 정렬할 때, 여분의 메모리가 충분할 때!
2. 반대로, 많은 데이터를 정렬하고 싶은데 메모리가 부족할 때!!!! --> 분할정복이 빛이 나게 된다
3. Quick정렬의 경우, 최악의 경우가 O(N^2)이므로 반드시 O(NlogN)으로 정렬하고 싶을 때!
정렬 과정
- 의외로 설명은 간단(?)하다.
1. 배열을 쪼개고 쪼개서 분할한다
2. 더 이상 쪼갤 수 없을 때, 왼쪽 파티션과 오른쪽 파티션을 정렬하여 합친다!
3. 이러한 작업을 원본 배열이 될 때까지 반복한다!!!
- 이러한 과정을 끝날 때까지 반복하면 정렬이 끝난다~!
코드 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package dataStructure;
import java.util.Arrays;
/**
* [ 정렬 알고리즘 ] - Mergesort
* 시간복잡도 - O(NlogN) - 최악의 경우와 평균이 동일
* 공간복잡도 - O(N)
* 분할정복의 대표적인 알고리즘의 예시로, 시간복잡도가 항상 일정하기 유지된다는 것이 장점이다
* 배열을 나누고 임시배열을 또 따로 만들어야 하는 메모리 낭비가 있지만
* 안정적으로 이용할 수 있다는 것에 장점을 두고 있다.
* N이 1백만일 때, 79ms의 시간 소요가 된다!
* @author huisam
*
*/
public class MergeSort {
private static int SIZE = 1000000;
/** 배열을 저장할 변수 */
private int arr[] = new int[SIZE];
/** 정렬할 때 값을 저장할 임시 변수 */
private int sorted[] = new int[SIZE];
/** 객체 생성시 난수 뿌리기 */
public MergeSort() {
for (int i = 0; i < SIZE; i++) {
arr[i] = (int) (Math.random() * 100) + 1;
}
}
/**
* 배열을 출력할 메서드
*/
public void print() {
System.out.println(Arrays.toString(arr));
}
/**
* MergeSort 구현 메서드
* 1. 왼쪽과 오른쪽을 파티셔닝 한다.
* 2. 왼쪽 오른쪽을 나누었으면 정렬하면서 합친다!!
*/
public void mergeSort(int start, int end) {
if(start < end) {
int mid = (start + end) /2;
mergeSort(start, mid);
mergeSort(mid+ 1, end);
merge(start, mid, end);
}
}
/**
* 1.왼쪽 배열과 오른쪽 배열에 대하여 순차적으로 값을 비교한다!
* 2.더 작은 값이 있다면 임시 배열에 저장하고 인덱스를 늘린다
* 3.이러한 작업을 할 수 있을때 까지 반복한다!
* 4.마지막에 남은 배열에 모든 원소를 임시 배열에 붙인다!
* 5.최종적으로 임시배열을 원래 배열로 복사한다!
* @param start 왼쪽 배열의 시작
* @param mid 왼쪽 배열의 끝
* @param end 오른쪽 배열의 끝
*/
private void merge(int start, int mid, int end) {
int i = start; // 왼쪽 인덱스
int j = mid + 1; // 오른쪽 인덱스
int k = start; // 복사할 배열의 인덱스
while(i <= mid && j <= end) {
if(arr[i] <= arr[j])
sorted[k++] = arr[i++];
else
sorted[k++] = arr[j++];
}
if(mid < i) {
for (int l = j; l <= end; l++) {
sorted[k++] = arr[l];
}
}
else {
for (int l = i; l <= mid; l++) {
sorted[k++] = arr[l];
}
}
for (int l = start; l <= end; l++) {
arr[l] = sorted[l];
}
}
public static void main(String[] args) {
MergeSort ms = new MergeSort();
// ms.print();
long time = System.currentTimeMillis();
ms.mergeSort(0, 999999);
System.out.println("걸리는 시간 : " + (System.currentTimeMillis() - time) + "ms");
// ms.print();
}
}
|
cs |
참고
Sorting Algorithm을 비판적으로 바라보자
위키백과 - 합병정렬
반응형
'Developer > Algorithm' 카테고리의 다른 글
[Path Algorithm] Bellman-Ford & SPFA (0) | 2019.05.01 |
---|---|
TopologicalSort - 위상정렬 (0) | 2019.04.19 |
InsertionSort(삽입정렬)이란? (0) | 2019.04.05 |
Quicksort(퀵정렬)이란? (0) | 2019.04.03 |