Mergesorting
합병정렬
분할정복법
- 분할 : 해결하고자 하는 문제를 작은 크기의 동일한 문제들로 분할
- 정복 : 각각의 작은 문제를 순환적으로 해결
- 합병 : 작은 문제의 해를 합하여(merge) 원래 문제에 대한 해를 구함
- 두개의 정렬된 리스트를 하나로 합치는 부분을 코드로 작성을 해야한다.
- 두개의 정렬이 각각 정렬이 되어있다.
- 가장 작은 값은 두개의 정렬의 각각 앞쪽값이다.
- 2개의 정렬된 정렬을 하나의 추가배열을 만들어서 이용을 한다.
- i는 첫번째 배열에서 가장 작은 값, j는 두번째 배열에서 가장 작은 값, k는 합쳐진 배열에서 가장 작은 값을 의미한다.
- A[i]와 B[j]를 비교해서 C[0]의 값을 구한다.
- mergeSort는 기본적으로 Recursion이다. 기본적으로 매개변수를 지정해야한다.
- mergeSort의 매개변수 A[]는 배열이고, p는 시작인덱스, r은 마지막인덱스를 나타낸다.
- p >= r의 경우 데이터가 1이거나 0이다. 정렬할 필요가 없어진다.
- 분할해서 문제를 풀어야하므로 배열을 반으로 쪼개야된다. 그래서 p,r의 중간값인 q를 설정한다. 가운데값은 홀수냐 짝수냐에 따라 다르다.
- p~q까지 recursion으로 정렬하고, q+1~r까지 정렬을 한다.
- merge는 배열A의 p~q까지의 정렬된 배열과, q+1~r까지의 정렬된 배열을 합쳐서 하나의 배열로 만드는 것이다.
public class MergeSort {
public static void merge(int [] data, int p, int q, int r) {
int i = p;
int j = q+1;
int k = p;
int [] tmp = new int[data.length];
// tmp라는 합쳐질 배열의 이름
while (i <= q && j <= r) {
// i<=q는 아직 앞쪽에 데이터가 남아있다는 뜻이다. j<=r은 뒷쪽배열에 아직 데이터가 있다.
if (data[i] <= data[j])
tmp[k++] = data[i++];
// data[i]가 data[j]보다 작으면 data[i]가 tmp[k]로 내려오고, k와 i의 값을 1씩 증가시킨다.
tmp[k++] = data[j++];
// data[i]와 data[j]를 비교를 해서 더 작은값을 tmp[k]에다가 넣는다.
}
// 위의 while문을 빠져나온것은 i가 q를 넘어갔거나. j가 r을 넘어간것이다.
while (i <= q)
tmp[k++] = data[i++];
// 앞쪽 배열에 데이터가 남아있다면 그대로 데이터를 옮겨라
while (j <= r)
tmp[k++] = data[j++];
// 뒤쪽 배열에 데이터가 남아있으면 그대로 데이터를 옮겨라
//tmp에 있는 데이터를 원래데이터 data[]에 그대로 다시 옮겨줘야한다.
for (int a = p; a <= r; a++)
data[a] = tmp[a];
}
}
- n개의 데이터를 정렬하는데 걸리는 시간은, T(n/2)이 2번 필요하다. merge하는데 필요한 시간은 n이다.
- T(n) = 2T(n/2) + n이다.
Written on July 21, 2018