在上一篇博客中已經討論過關於快速排序如何優化的問題,此次就直接貼出完整已優化的代碼。此代碼優化步驟包括了三數取中選取樞軸+小數組使用插排+三向切分。git
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100 //用於要排序數組的最大值
#define MAX_LENGTH_INSERT_SORT 7 //數組長度閾值
typedef struct //定義一個順序表結構 {
int r[MAXSIZE+1]; //用於存儲要排序數組,r[0]用做哨兵或者臨時變量
int length; //用於存儲順序表的最大長度
}SqList;
void swap(SqList *L,int i,int j);
void InsertSort(SqList *L);
void PickMiddle(SqList *L,int low,int high);
int Partition(SqList *L,int low,int high);
void QSort(SqList *L,int low,int high);
void QuickSort(SqList *L);
int main() {
int i;
int array[] = {39,80,76,41,13,29,50,78,30,11,100,7,41,86,41,11,30};
SqList L;
L.length = sizeof(array)/sizeof(array[0]); //獲取數組長度
printf("Before sorting:");
for(i=0;i<L.length;i++)
{
L.r[i+1]=array[i]; //把數組存入順序表結構
printf("%d ",L.r[i+1]);
}
printf("\n\n");
QuickSort(&L);
printf("After sorting: ");
for(i=0;i<L.length;i++) //輸出排序後的數組
printf("%d ",L.r[i+1]);
return 0;
}
/*元素交換函數*/
void swap(SqList *L,int i,int j) {
int temp=L->r[i];
L->r[i]=L->r[j];
L->r[j]=temp;
}
/*快速排序主函數*/
void QuickSort(SqList *L) {
QSort(L,1,L->length); //L->r[0]做爲哨兵,low從1開始
}
/*快排處理函數*/
void QSort(SqList *L,int low,int high) {
/* if-else條件語句用於處理小數組處理的問題, * 具體序列值說法不一,此處定爲7(也有認爲50合理)。若數組 * 個數較小採用簡單插入排序,效率更高。*/
if((high-low) <= MAX_LENGTH_INSERT_SORT)
{
InsertSort(L);
return;
}
PickMiddle(L,low,high); //三數取中函數
int lt = low; //low此時爲樞軸位置
int gt = high;
int i = low +1; //low位置的元素爲樞軸元素,因此用於比較的元素從low+1開始
L->r[0]=L->r[low]; //將樞軸的元素儲存到L->r[0]中
while(i<=gt)
{
if(L->r[i] < L->r[0]) //小於樞軸元素的放在lt左邊
swap(L,lt++,i++); //即交換lt和i位置的元素,此時樞紐位置(lt)右移一位,i也所以右移
else if(L->r[i] > L->r[0]) //大於樞軸元素的放在gt右邊
swap(L,i,gt--); //交換i和gt位置的元素,gt須要左移,i因爲變爲gt位置元素,因此不須要移動
else //相等時,無需交換,只需把i右移一位
i++;
}
//lt-gt的元素已經排定(相等的元素),只需對it左邊和gt右邊的元素進行遞歸求解
QSort(L,low,lt-1);
QSort(L,gt+1,high);
}
/*三數取中函數*/
void PickMiddle(SqList *L,int low,int high) {
int mid = (low+high) / 2; //計算數組中間元素的下標
if(L->r[low]>L->r[high])
swap(L,low,high); //目標[low]<=[high]
if(L->r[mid]>L->r[high])
swap(L,mid,high); //目標[mid]<=[high]
//以上兩步保證把最大移到最右端
if(L->r[mid]>L->r[low])
swap(L,mid,low); //目標[low]>=[mid],即把中間值移到最左端
//此時,L->r[mid] <= L->r[low] <= L->r[high]
}
/*直接插入排序*/
void InsertSort(SqList *L) {
int i,j;
for(i=2; i<=L->length; i++)
{
if(L->r[i] < L->r[i-1])
{
L->r[0]=L->r[i];
for(j=i-1; L->r[j] > L->r[0]; j--)
L->r[j+1]=L->r[j];
L->r[j+1]=L->r[0];
}
}
}
複製代碼
運行結果爲:github