[Algorithm] - 정렬의 모든 것(Sort)

내용

모든 정렬에 대한 정리를 해보겠다.

코드는 ‘n개를 입력받아 오름차순으로 정렬함’을 기준으로 한다.

Quick-Sort [퀵정렬]

퀵정렬은 말그대로 빠른 정렬이다.

퀵정렬에는 기준을 잡는 값 pivot이 있다.

복잡도

  • 평균 시간 복잡도 : O(N*LogN)
  • 최악 시간 복잡도 : O(N^2)

퀵정렬이라는 이름답게 평균적으로 빠르고 자주쓰인다.

하지만 최악의 경우 엄청 오래 걸린다.

코드

#include <stdio.h>

void sort(int *arr, int start, int end){
    
    if(start>=end){//엇갈리면
        return;
    }
    
    int pivot = start;    //피봇
    int i = pivot+1;    //i는 피봇 다음원소
    int j = end;    //j는 마지막 원소
    int temp;
    
    while(i<=j){//i가 더 커지면 종료
        //피봇 보다 큰 값 만날 때 까지
        while(i<=end && arr[i]<=arr[pivot]){
            ++i;
        }
        //피봇 보다 작은 값 만날 때 까지
        while(j>start && arr[j]>=arr[pivot]){
            --j;
        }
        
        //위에서 계산된 i와 j가 만나거나 엇갈리면 종료
        if(i>=j) break;
        
        //두 원소 교환
        temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    
    //피봇 정렬 완료
    temp = arr[j];
    arr[j] = arr[pivot];
    arr[pivot] = temp;
    
    sort(arr, start, j-1);    //피봇 중심으로 왼쪽부분 분할
    sort(arr, j+1, end);    //피봇 중심으로 오른쪽부분 분할
}

int main(){
    
    int t;
    scanf("%d",&t);
    
    int arr[1001];
    for(int i=0;i<t;i++) scanf("%d",&arr[i]);
    
    sort(arr, 0, t-1);
    
    //출력
    for(int i=0;i<t;++i){
        printf("%d ", arr[i]);
    }
    
    return 0;
}

Merge-Sort [병합정렬]

병합정렬은 분할정복법을 사용한 알고리즘이다.

병합정렬은 배열을 작은크기로 줄이고 정렬하여 합치는 정렬방법이다.

복잡도

  • 평균 시간 복잡도 : O(N*LogN)
  • 최악 시간 복잡도 : O(N*LogN)

병합정렬은 최악의 경우에도 평균적인 시간복잡도를 가진다.

코드

# include <stdio.h>
# define MAX_SIZE 1000001
int sorted[MAX_SIZE];// 정렬된 값 담을 배열

// i: 정렬된 왼쪽 리스트에 대한 인덱스
// j: 정렬된 오른쪽 리스트에 대한 인덱스
// k: 정렬될 리스트에 대한 인덱스

void merge(int list[], int left, int mid, int right){
  int i, j, k, l;
  i = left;
  j = mid+1;
  k = left;//정렬될 인덱스

  /* 분할 정렬된 list의 합병 */
  while(i<=mid && j<=right){//왼쪽배열,오른쪽배열 인덱스들이 각 배열을 벗어나지 않을 경우
    if(list[i]<=list[j])//인덱스 i값이 작으면
      sorted[k++] = list[i++];
    else
      sorted[k++] = list[j++];
  }

  if(i>mid){//왼쪽배열 인덱스가 왼쪽배열 벗어날 경우
    for(l=j; l<=right; l++)
      sorted[k++] = list[l];//오른쪽배열 남은 값 복사
  }
  else{//오른쪽배열 인덱스가 오른쪽배열 벗어날 경우
    for(l=i; l<=mid; l++)
      sorted[k++] = list[l];//왼쪽배열 남은 값 복사
  }

  // 배열 sorted[](임시 배열)의 리스트를 배열 list[]로 재복사
  for(l=left; l<=right; l++){
    list[l] = sorted[l];
  }
}

// 합병 정렬
void merge_sort(int list[], int left, int right){
  int mid;

  if(left<right){
      mid = (left+right)/2; // 중간 위치를 계산
      
    merge_sort(list, left, mid); // 앞쪽 부분 나누기
    merge_sort(list, mid+1, right); // 뒤쪽 부분 나누기
      
    merge(list, left, mid, right);//정렬 후 배열 합하기
  }
}

int main(){
    int t;
    scanf("%d",&t);
    
    int list[MAX_SIZE];
    for(int i=0;i<t;i++) scanf("%d", &list[i]);
  
    merge_sort(list, 0, t-1);

    for(int i=0; i<t; i++){//출력
        printf("%d\n", list[i]);
    }
}

요약

  • 아직 더올릴거다.