
| 단순하지만 비효율적인 방법 | 복잡하지만 효율적인 방법 | 정렬 알고리즘의 안정성 |
|---|---|---|
| 삽입정렬(insertion sort) 선택정렬(selection sort) 버블정렬(bubble sort) | 퀵정렬(quick sort) 히프정렬(heap sort) 합병정렬(merge sort) 기수정렬(radix sort) | 동일한 키 값을 갖는 레코드들의 상대적인 위치가 정렬 후에도 바뀌지 않음 |


#define SWAP(x, y, t) ( (t)=(x), (x)=(y), (y)=(t) )
void selection_sort(int list[], int n) {
int i, j, least, temp;
for(i=0; i<n-1; i++) {
least = i;
for( j=i+1; j<n; j++)
if(list[ j]<list[least]) least = j; // 최소값 탐색
SWAP(list[i], list[least], temp);
}
}
![]() | ![]() |
|---|

// 삽입정렬
void insertion_sort(int list[], int n) {
int i, j, key;
for(i=1; i<n; i++){
key = list[i];
for( j=i-1 ; j>=0 && list[ j]>key ; j--)
list[ j+1] = list[ j]; // 레코드의 오른쪽 이동
list[ j+1] = key;
}
}
| 정렬되지 않은 {69, 10, 30, 2, 16, 8, 31, 22}의 자료들을 셸 정렬 | |
|---|---|
| 원소의 개수가 8개이므로 간격 gap은 4에서 시작 gap=4 이므로 간격이 4인 원소들을 같은 부분 집합으로 만들면 4개의 부분 집합이 만들어진다 | ![]() |
| 첫 번째 부분 집합 {69, 16}에 대해서 삽입 정렬을 수행하여 정렬. | ![]() |
| 두 번째 부분 집합 {10, 8}에 대해서 삽입 정렬 수행 | ![]() |
| 세 번째 부분 집합 {30, 31}에 대해서 삽입 정렬을 수행하는데, (30<31) 이므로 자리 교환은 이루어지지 않는다. | ![]() |
| 네 번째 부분 집합 {2, 22}에 대해서 삽입 정렬을 수행하는데,(2<22) 이므로 자리 교환은 이루어지지 않는다 | ![]() |
| gap을 2로 변경하고 다시 셸 정렬 시작. gap=2 이므로 간격이 2인 원소들을 같은 부분 집합으로 만들면 2개의 부분 집합이 만들어진다. | ![]() |
| 첫 번째 부분 집합 {16, 30, 69, 31}에 대해서 삽입 정렬을 수행하여 정렬 | ![]() |
| 두 번째 부분 집합 {8, 2, 10, 22}에 대해서 삽입 정렬을 수행하여 정렬 | ![]() |
// gap 만큼 떨어진 요소들을 삽입 정렬. 정렬의 범위는 first에서 last
inc_insertion_sort(int list[], int first, int last, int gap) {
int i, j, key;
for(i=first+gap ; i<=last ; i=i+gap){
key = list[i];
for(j=i-gap ; j>=first && key<list[ j] ; j=j-gap)
list[j+gap]=list[ j];
list[j+gap]=key;
}
}
//
void shell_sort( int list[], int n ) {
int i, gap;
for( gap=n/2 ; gap>0 ; gap = gap/2 ) {
for(i=0 ; i<gap ; i++) // 부분 리스트의 개수는 gap
inc_insertion_sort(list, i, n-1, gap);
}
}
#define SWAP(x, y, t) ( (t)=(x), (x)=(y), (y)=(t) )
void bubble_sort(int list[], int n){
int i, j, temp;
for( i=n-1; i>0 ; i-- ){ //마지막 원소부터 정렬됨
for( j=0; j<i ; j++ ) // 앞뒤의 레코드를 비교한 후 교환
if ( list[ j] > list[ j+1] )
SWAP(list[ j], list[ j+1], temp);
}
}




![]() | ![]() |
|---|
합병정렬 소스코드
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);
}
}
// i는 정렬된 왼쪽리스트에 대한 인덱스
// j는 정렬된 오른쪽리스트에 대한 인덱스
// k는 정렬될 리스트에 대한 인덱스
void merge(int list[], int left, int mid, int right){
int sorted[MAX_SIZE]; // 임시 공간 필요
int i, j, k, l;
i=left; j=mid+1; k=left;
// 분할 정렬된 list의 합병
while(i<=mid && j<=right){
if(list[i]<=list[ j]) 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];
}
합병정렬 복잡도 분석