



#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);
}
}
i가 n-1까지인 이유는 마지막 인덱스는 어차피 최대값이니 정렬할 필요가 없다


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;
}
}
인덱스i=1부터인 이유는 0번째 인덱스는 정렬된것으로 보기 때문


#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);
}
}

간격 5 -> 간격 3 -> 간격 1로 부분 리스트 정렬 수행한것임
간격(gab) 이 1이면 삽입정렬과 어차피 같아지지만 셸정렬을 하면 어느정도 정렬이 되므로 경제적
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 ) // n = size
{
int i, gap;
for (gap=1; gap<=n/9; gap=3*gap+1); //부분리스트의 크기는 9보다 큰 수부터 시작
while (gap>0) {
for(i=0;i<gap;i++) // 부분 리스트의 개수는 gap: n/9 보다 큼
inc_insertion_sort(list, i, n-1, gap);
gap /= 3;
}
}



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]) 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); // 합병
}
}

void quick_sort(int list[], int left, int right)
{
if(left<right){
int q=partition(list, left, right);
quick_sort(list, left, q-1);
quick_sort(list, q+1, right);
}
}
int q는 partition함수에 의해 받는 피폿의 인덱스 값이다
피벗(pivot): 가장 왼쪽 숫자라고 가정
두개의 변수 low와 high를 사용한다.
low는 피벗보다 작으면 통과, 크거나 같으면 정지
high는 피벗보다 크면 통과, 작거나 같으면 정지
정지된 위치의 숫자를 교환
low와 high가 교차하면 종료

int partition(int list[], int left, int right)
{
int pivot, temp;
int low,high;
low = left;
high = right+1;
pivot = list[left];
do {
do
low++;
while(low<=right && list[low]<pivot);
do
high--;
while(high>=left && list[high]>pivot);
if(low<high) SWAP(list[low], list[high], temp);
} while(low<high);
SWAP(list[left], list[high], temp);
return high;
}
그러나 최악의 경우(극도로 불균등한 리스트의 경우) O(n^2)->중앙값을 피벗으로 선택하면 불균등 분할 완화 가능하다

Reference (https://jbhs7014.tistory.com/180)
C언어로 쉽게 풀어 쓴 자료구조, 천인국, 공용해, 하상호_2019
상명대학교 홍철의 교수님 강의자료