### 排序算法(二)
```c
/////////////////////////////////////////////////////////////
//歸併排序(遞歸)
//時間複雜度:O(N * logN)
//空間複雜度:O(N)
//穩定性:穩定排序
////////////////////////////////////////////////////////////
void _MergeArray(int array[], int64_t beg, int64_t mid, int64_t end, int* tmp){
int64_t cur1 = beg;
int64_t cur2 = mid;
int64_t tmp_index = beg;
while(cur1 < mid && cur2 < end){
if(array[cur1] < array[cur2]){
tmp[tmp_index++] = array[cur1++];
}else{
tmp[tmp_index++] = array[cur2++];
}
}
while(cur1 < mid){
tmp[tmp_index++] = array[cur1++];
}
while(cur2 < end){
tmp[tmp_index++] = array[cur2++];
}
//進行歸併的時候處理的區間是 array[beg, end),
//對應的會把這部分區間元素填充到 tmp[beg, end)
memcpy(array + beg, tmp + beg, sizeof(int) * (end - beg));
return;
}
void _MergeSort(int array[], int64_t beg, int64_t end, int* tmp){
if(end - beg <= 1){
//要麼一個元素,要麼沒有元素,要麼非法區間
return;
}
int64_t mid = beg +(end - beg) / 2;
//此時有了兩個區間[beg, mid), [mid, end)
_MergeSort(array, beg, mid, tmp);
_MergeSort(array, mid, end, tmp);
_MergeArray(array, beg, mid, end, tmp);
return;
}
void MergeSort(int array[], size_t size){
int* tmp = (int*)malloc(sizeof(int) * size);
_MergeSort(array, 0, size, tmp);
free(tmp);
}
/////////////////////////////////////////////////////////////
//歸併排序
//時間複雜度:O(N * logN)
//空間複雜度:O(N)
//穩定性:穩定排序
////////////////////////////////////////////////////////////
void MergeSortByLoop(int array[], size_t size){
if(size <= 1){
return;
}
int* tmp = (int*)malloc(sizeof(int) * size);
size_t gap = 1;
for(; gap < size; gap *= 2){
//在當前gap下,使用i幫助我們完成所有長度爲gap的區間合併
size_t i = 0;
for(;i < size; i += 2 * gap){
size_t beg = i;
size_t mid = i + gap;
//爲了防止 mid超出數組最大size
if(mid > size){
mid = size;
}
size_t end = i + 2 * gap;
if(end > size){
end = size;
}
_MergeArray(array, beg, mid, end, tmp);
}
}
free(tmp);
}
/////////////////////////////////////////////////////////////
//快速排序
//時間複雜度:O(N * logN) 最壞情況O(N ^ 2)
//空間複雜度:最壞O(N)
//穩定性:不穩定排序
////////////////////////////////////////////////////////////
//取一個基準值,倒騰,使前半部分小於基準值,後半部分大於基準值
//如果逆序,快排就不合適,遞歸可能很深,針對小數組不合適
// C++ STL std::sort
// 1.選取基準值的的方法:三個元素選中間值
// 2.當遞歸深度達到一定值的時候,就不在繼續遞歸,而是把排序算法轉化成堆排序
// 3.當遞歸達到一定程度之後,子區間的元素個數已經比較小,把排序算法編程插入排序
//交換法
int64_t Partion(int array[], int64_t beg, int64_t end){
if(end - beg <= 1){
return beg;
}
int64_t left = beg;
int64_t right = end - 1;
//數組的最後一個元素作基準元素
int key = array[right];
//從左往右找一個大於key的值
while(left < right){
while(left < right && array[left] <= key){
++left;
}
//從右往左找一個小於key的值
while(left < right && array[right] >= key){
--right;
}
if(left < right){
Swap(&array[left], &array[right]);
}
}
//最後把left指向的位置和基準值交換
Swap(&array[left], &array[end - 1]);
return left;
}
void _QuickSort(int array[], int64_t beg, int64_t end){
if(end - beg <= 1){
return;
}
//[beg, mid),左半區間
//[mid + 1, end],右半區間
//
int64_t mid = Partion(array, beg, end);
_QuickSort(array, beg, mid);
_QuickSort(array, mid + 1, end);
}
void QuickSort(int array[], size_t size){
_QuickSort(array, 0, size);
return;
}
//挖坑法
int64_t Partion2(int array[], int64_t beg, int64_t end){
if(end - beg <= 1){
return beg;
}
int64_t left = beg;
int64_t right = end - 1;
//數組的最後一個元素作基準元素
int key = array[right];
while(left < right){
while(left < right && array[left] <= key){
++left;
}
if(left < right){
array[right--] = array[left];
}
while(left < right && array[right] >= key){
--right;
}
//循環可以退出,意味着 right 指向了一個小於基準值的元素,
//就可以把這個值填到剛纔left 指向的坑裏
//一旦複製操作完成,right自身又成了一個坑
if(left < right){
array[left++] = array[right];
}
}
//一旦left 和right重合,說明整個區間整理完畢
//但是還有一個坑
array[left] = key;
return left;
}
//3.雙指針前移法
//略
//非遞歸版本快速排序
void QuickSortByLoop(int array[], size_t size){
if(size <= 1){
return;
}
LinkStack stack;
LinkStackInit(&stack);
int64_t beg = 0;
int64_t end = size;
LinkStackPush(&stack, beg);
LinkStackPush(&stack, end);
while(1){
int ret = LinkStackTop(&stack, &end);
if(ret == 0){
//棧爲空,說明排序結束
break;
}
LinkStackPop(&stack);
LinkStackTop(&stack, &beg);
if(end - beg <= 1){
continue;
}
int64_t mid = Partion(array,beg, end);
LinkStackPush(&stack, beg);
LinkStackPush(&stack, mid);
LinkStackPush(&stack, mid + 1);
LinkStackPush(&stack, end);
}
}
/////////////////////////////////////////////////////////////
//計數排序
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
//奇數排序
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
//睡眠排序:創建線程,根據退出時間
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
//猴子排序:無線猴子定理
/////////////////////////////////////////////////////////////
“`