直接插入排序、希爾排序、快速排序、堆排序算法比較

 直接插入排序、希爾排序、快速排序、堆排序算法比較 

進行典型內部排序算法的比較,隨機產生整數樣本,進行四種排序,並比較各種排序算法的執行時間。

 

#include "stdio.h"
#include "stdlib.h" 
#include "conio.h"
#include "time.h"

#define MAXSIZE 20

typedef struct{
    int key;
}RedType;
typedef struct{            //定義順序表的存儲結構 
    RedType *r;            //存儲空間基址,r[0]閒置或用作哨兵或用作緩衝區/
    int length;            //順序表的長度 
}SqList;


void InitSqList(SqList *L){
    L->r=(RedType *)malloc((MAXSIZE+1)*sizeof(RedType));
    L->length=0;
}//InitSqList

void CreateSqList(SqList *L){//輸入數據元素個數,隨機產生整數樣本 
    int i;
    
    srand((unsigned)time(0));
    
    printf("\n請輸入順序表的長度: ");
    scanf("%d",&L->length);
    
    for ( i=1; i<=L->length; i++){
        L->r[i].key=rand()%100;//隨機產生整數樣本
    }
    printf("\n\n未排序的數據爲:\n");
    for( i=1; i<=L->length; i++)
        printf("%8d",L->r[i]);
}//CreateSqList
/*************************************直接插入排序********************************************/ 
void InsertSort(SqList *L){//直接插入排序 
    int i,j;
    
    if(!L->length){
        printf("該順序表爲空!");
    }
    
    for(i=2; i<=L->length; i++)
        if(L->r[i].key < L->r[i-1].key){
            L->r[0].key=L->r[i].key;//複製哨兵
            for(j=i-1; L->r[0].key<L->r[j].key; j--){
                L->r[j+1].key=L->r[j].key;//元素後移 
            }//for
            L->r[j+1].key = L->r[0].key;//元素插入 
        }//if
}//InsertSort

/*************************************希爾排序********************************************/ 
void shellSort(SqList *L,int dk){//希爾排序
    int i,j; 
    for(i=dk+1; i<=L->length; i++)
        if(L->r[i].key < L->r[i-1].key){
             L->r[0].key=L->r[i].key;//複製哨兵
             for(j=i-dk; j>0&&L->r[0].key<L->r[j].key; j-=dk)
                 L->r[j+dk].key = L->r[j].key;//元素後移 
             L->r[j+dk].key = L->r[0].key;//元素插入
         }//if
} //shellSort
void shellInsert(SqList *L){
    int dk;
    for(dk=L->length; dk>0; dk=dk/2){
        shellSort(L,dk);//每次的增量都爲dk/2,最終變爲1 
    }                    //當dk變爲1是就是最基本的直接插入排序 
}//shellSqList

/*************************************快速排序********************************************/ 
int Partition(SqList *L, int low, int high){
    int pivotkey; 
    L->r[0].key = L->r[low].key;
    pivotkey = L->r[low].key;
    while(low<high){
        while(low<high && L->r[high].key >= pivotkey) --high;
        L->r[low].key = L->r[high].key;
        while(low<high && L->r[low].key <= pivotkey) ++low;
        L->r[high].key = L->r[low].key;
    }//while
    //當low=high時跳出循環 
    L->r[low].key = L->r[0].key; 
    return low;
}//Partition

void  QSort(SqList *L, int low, int high){//遞歸快速排序 
    int pivotloc;
    if(low<high){
        pivotloc = Partition(L, low, high);
        QSort(L, low, pivotloc-1);
        QSort(L, pivotloc+1, high);
    }
}//QSort

/*************************************堆排序********************************************/
void HeapAdjust(SqList *L, int s, int m){
    int j,rc;
    rc = L->r[s].key;
    for(j=2*s; j<=m; j*=2){
        if(j<m && L->r[j].key < L->r[j+1].key) ++j;
        if(rc > L->r[j].key) break;
        L->r[s].key = L->r[j].key;
        s = j;
    }
    L->r[s].key = rc; 
}//HeapAdjust
 
void HeapSort(SqList *L){
    int i,temp;
    for (i=L->length/2; i>0; i--)
        HeapAdjust(L,i,L->length);
    for (i=L->length; i>1; i--){
        temp = L->r[1].key;
        L->r[1].key = L->r[i].key;
        L->r[i].key = temp;
        HeapAdjust(L,1,i-1);
    }
}//HeapSort

/*************************************輸出函數********************************************/ 
void outputSqList(SqList *L){//輸出排序之後的元素 
    int i;
    
    printf("\n該順序表的長度爲::%d\n",L->length);
    
    printf("\n\n排序了的數據爲 : \n");
    for(i=1; i<=L->length; i++){
        printf("%8d",L->r[i].key);
    }
    printf("\n");
}//outputSqList
/*************************************複製鏈表函數********************************************/ 
void CopySqList(SqList *L, SqList *L_COPY){
    int i;
    if ( !L->length ){
        printf("該順序表爲空!\n");
    }
    
    else{
        for (i=1; i<=L->length; i++)
            L_COPY->r[i].key = L->r[i].key;
        L_COPY->length = L->length;
    }
}//CopySqList
int main(){
    SqList L, L_COPY;//L爲初始順序表 ,L_COPY爲L的副本,用於排序
    clock_t start,finish;
    int select,flag;//用戶輸入的選項 
    flag = 1;
    InitSqList(&L);
    InitSqList(&L_COPY);
    CreateSqList(&L);
    while(flag){
        //mnum=0;cnum=0;
        CopySqList(&L,&L_COPY);
        printf("\n請輸入選:\n1. 直接插入排序\n2. 希爾排序\n3. 快速排序\n4. 堆排序\n5.退出\n");
        scanf("%d",&select);
        switch(select){
            case 1:
                start=clock();
                InsertSort(&L_COPY);
                finish=clock();
                break;
            case 2:
                start=clock();
                shellInsert(&L_COPY);
                finish=clock();
                break;
            case 3:
                start=clock();
                QSort(&L_COPY,1,L.length);
                finish=clock();
                break;
            case 4:
                start=clock();
                HeapSort(&L_COPY);
                finish=clock();
                break;
            case 5:
                flag=0;
                exit(0);
        }
        outputSqList(&L_COPY);
        //printf("\n排序花的時間 : %lf Seconds\n",double(finish-start));
    }
    return 0;
}


最後對,這些排序算法的複雜度進行一下簡單的比較

算法種類 時間複雜度 空間複雜度 是否穩定
最好情況 平均情況 最壞情況
直接插入排序 O(n) O(n²) O(n²) O(1)
希爾排序   O(1)
快速排序 O(nlog₂n) O(nlog₂n) O(n²) O(log₂n)
堆排序 O(nlog₂n) O(nlog₂n) O(nlog₂n) O(1)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章