실버5 : 정렬 문제이다.

생각

정렬 문제이다. merge sort(합병 정렬)을 구현해보고자 시도했다.

알고리즘

기본적인 병합 정렬의 알고리즘은 다음과 같다.
위키 백과 - 합병 정렬 좀 더 자세한 설명

partition

나누는 방법은 간단하다. 시작과 끝점을 주고, 반을 자르면서 들어가는 것이다. 가장 작은 단위는 1개의 원소를 가질 때이다. 이 위치에 다다랐을 때 합치는 연산을 수행하면서 거꾸로 올라가면 된다.

merge

합칠 때는, 두 개의 바구니에 담긴 원소들을 비교하면서 새로운 바구니에 차곡차곡 담아두어야 한다. 이 때, 한 바구니의 최댓값이 다른 바구니의 중간 원소보다 작을 경우에 나머지 원소들을 한꺼번에 밀어 넣어주어야 한다는 것을 잊지 말자. 또한 최종 바구니에 다 넣었다면, 다른 바구니들을 비교하는데 있어 정렬된 바구니가 필요하므로 원래 배열에 밀어넣어준다.

Code

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
using namespace std;
 
int N;
int *a, *temp;
 
void merge(int start, int end) {
    int mid = (start+end)/2;
    int i = start, j = mid+1, k = start;
 
    while (i <= mid && j <= end) {
        if (a[i] <= a[j]) temp[k++] = a[i++];
        else temp[k++] = a[j++];
    }
 
    int restLoc = i > mid ? j : i; // 병합중 한쪽 바구니가 끝난 경우 나머지의 위치를 결정해줌
    while (k <= end) temp[k++] = a[restLoc++]; // (end-start)개수만큼을 채워야 하니, 나머지들을 넣어줌
    for (int i = start; i <= end; i++)  a[i] = temp[i]; // temp배열에 넣은 녀석들을 원래 것으로 업데이트 해줌
}
 
void partition(int start, int end){
    if (end <= start) return;
 
    int mid = (start+end)/2;
    partition(start, mid);
    partition(mid+1, end);
    merge(start, end);
}
 
 
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
 
    cin >> N;
    a = new int[N+1];
    temp = new int[N];
    for (int i = 0; i < N; i++) cin >> a[i];
 
    partition(0, N-1);
 
    for (int i = 0; i < N; i++) cout << a[i] << '\n';
 
}
 

Reference