알고리즘/분할정복

[알고리즘] 분할정복 - 합병정렬(1)

HYJJ 2022. 2. 15. 14:35

분할정복의 개념을 잡기 위해 합병정렬 코드를 작성해보았다.

처음의 개념은 다음과 같다.

 

divide()라는 메소드를 생성하여 배열을 재귀적으로 나누는 것을 생각했다.

소스코드는 다음과 같다.

 private static void divide(int[] arr, int start, int end) {
        int mid;
        while(start<end) {
            mid = (start+end)/2;
            divide(arr,start,mid);
            divide(arr, mid+1, end);
        }
    }

배열과 처음과 끝 인덱스를 파라미터로 넣어서 재귀적으로 호출한다.

그런데 호출 후에 배열을 어떻게 정렬할지 생각했고 새로운 메소드를 만들어서 나눈 값들로 비교해서 그 값을 다시 합한 값을 리턴해야겠다 생각했다.


가령 예를 들어보자.

 

divide()는 재귀적으로 호출하기 때문에

 

divide(arr, 1, 4) -> divide(arr,1,2) divide(arr,3,5)

divide(arr, 5, 8) -> divide(arr, 5,6) divide(arr,6,8)

 

이렇게 된다. while문의 조건은 start<end 이므로 

divide(arr,1,2) -> divide(arr,1,1) divide(arr,2,2)  

divide(arr,5,6) -> divide(arr, 5,5) divide(,6,6)

이렇게 최종적으로 남게 된다.

 

이렇게 재귀적으로 나눈 후의 코드에서 합병하여 정렬하는 메소드를 호출하면 정렬된 배열을 호출할 수 있을 것이라 생각했다. 즉 while문 안에서 divide()를 호출을 나눠서 하고 호출된 코드 아래에 정렬하는 메소드를 하나 추가하고자 한다.

 

conq() 메소드를 생각하는 데에는 시간이 오래 걸렸지만 조각낸 divide 에서의 배열 인덱스를 생각했을 때 구현하기 쉬워졌다. 처음 생각한 구조는 다음과 같다.

private static void divide(int[] arr, int start, int end) {
        int mid;
        while(start<end) {
            mid = (start+end)/2;
            divide(arr,start,mid);
            divide(arr, mid+1, end);
            arr = conq(arr, start, mid, end);
        }
    }

    private static int[] conq(int[] arr, int start, int mid, int end) {
        int[] ans = new int[arr.length];
        int i=0;

        while(start<mid && mid+1<end) {
            if(arr[start]>arr[mid+1]) {
                ans[++i] = arr[++mid+1];
            } else {
                ans[++i] = arr[++start];
            }
        }
        return ans;
    }

주르륵 짰는데 빈 ans 배열에 각각 정렬한 것을 넣고 리턴을 한다면 값이 비어있기 때문에 arr에 넣게되면 문제가 생기지 않을까 생각했다.

당연히 그렇다.

추가하지 않은 배열이 빈 배열이기 때문에 arr에 ans를 넣어버리면 빈값이라 호출할 때 비교를 못하는 상황이 발생하게 된다.

 

case 1

그렇다면 ans에 배열을 새로 추가하지 않고

1. tmp 변수를 생성한 후에

2. 비교 값을 일단 tmp에 넣어둔 다음

3. 비교를 하는 것이 어떨까?

-> conq() 메소드에서 배열을 리턴할 필요도 없고 arr에 ans를 넣는 번거로움도 사라질 거 같다.

: 그런데 하나만 비교할 경우만 가능하지 여러 변수를 비교하는 것은 어려울 듯 하다.

 

조금 더 고민해보겠다....