1. 程式人生 > >(資料結構排序的實驗四)快速,冒泡,簡單選擇,直接插入排序的c語言實現!!

(資料結構排序的實驗四)快速,冒泡,簡單選擇,直接插入排序的c語言實現!!

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">#include<stdio.h>
/****四種(冒泡,選擇,快速,插入)排序(遞增)下標都是從0開始的******/
int dig[1000];
    int n;
/*****1 (交換類) 氣泡排序***時間複雜度:O(n^2)***/
/**思想:一趟排序中(從起始位置開始)是將最大的關鍵字沉到陣列的底部。
n個數字排序,需要n-1趟,(假設就兩個數字,那麼只要一趟排序將最大的數值沉到陣列底部,此序列就是有序的啦)
    若序列本身就是有序的,那麼只要一趟即可,(為什麼還需要一趟呢?此趟是驗證序列都沒有發生交換,那麼此序列就是有序的)
**/</span>
void bubblingSort(int msort[],int num){
    int tmp;
    int flag;
    for(int i = 0;i < num-1;i++){
        flag = 0;
        for(int j = 0;j < num-i-1;j++){
            if(msort[j]>msort[j+1]){
                flag = 1;
                tmp = msort[j];
                msort[j] = msort[j+1];
                msort[j+1] = tmp;
            }
        }
        if(!flag) break;
    }
    for(int i = 0;i < num;i++){
        printf("%d ",msort[i]);
    }
    printf("\n");
}
/****2 (插入類) 直接插入排序***O(n^2)**/
/**
    思想:假設  2,5,7,10 已經排好了, 而接下來 數字式 6 ,一看就知道把 6 插入到5 和 7 之間。
怎麼插入呢?:邊插邊將陣列後移。6 比10 小, 那麼10 後移;6比7小,7後移;6比5大,那麼就把6插到5的後邊(5的後邊是個空的,因為前面已經把陣列後移啦!!)
**/
void insertSort(int msort[],int num){
    int tmp,j;
    for(int i = 1;i < num;i++){
        tmp = msort[i];
        for( j = i-1;j >= 0;j--){
            if(tmp<msort[j]){
                msort[j+1] = msort[j];
            }
            else{
                break;
            }
        }
        msort[j+1] = tmp;
    }
    for(int i = 0;i <num;i++){
        printf("%d ",msort[i]);
    }
    printf("\n");
}
 /****3 (選擇類) 簡單選擇排序****O(n^2)*/
 /**
    思想:第i 趟排序是指從n-i-1個記錄中,找出一個最小的記錄與第i個記錄交換。那麼第i個記錄就是較小的。
    列如:第一趟排序:從n個記錄中(從dig[1]...dig[n])找到最小的與第一個記錄交換,那麼第一個就是最小的。
            第二趟排序:從陣列後面的n-1個記錄中(從dig[2].....dig[n]),找出一個次小的,與第2個記錄交換。
    由此看來也是需要n-1趟排序
 **/
 void selectSort(int msort[],int num){
     int minn,pos;
    for(int i = 0;i < num-1;i++){
        minn = 1111111;
        for(int j = i;j < num;j++){
            if(msort[j]<minn){
                minn = msort[j];
                pos = j;
            }
        }
        if(i!=pos){
        int tmp;
        tmp = msort[pos];
        msort[pos] = msort[i];
        msort[i] = tmp;
        }
    }
    for(int i = 0;i <num;i++){
        printf("%d ",msort[i]);
    }
    printf("\n");
 }
/****4 (交換類) 快速排序***O(nlogn)**/
/**
    思想:待排的序列:dig[start].....dig[end],首先任意選取一個記錄(通常以第一個記錄作為樞軸(啥是樞軸?其實樞軸也沒啥概念(不用理解他)))
然後按照下述原則重新排列其餘記錄。將所有關鍵字(就是數組裡的值)小於它的記錄放在它的位置之前,將所有關鍵字大於它的記錄放在它的位置之後。
由此以該“樞軸”記錄最後所落的位置i作為分界線,將序列dig[start]....dig[end],分割成兩個兩個子序列dig[start]...dig[i-1](此序列的值都是無序的但是他們的值都小於樞軸的值)
和dig[i+1]....dig[end]((此序列的值也是無序的但是他們的值都大於樞軸的值)。這個過程為一次劃分。!!!
    劃分過程的具體實現:附設兩個指標(此處的指標並不是指向記憶體地址的指標,而是指向陣列的位置)low,high。low的初值=start,high = end;
設樞軸記錄的關鍵字為pivotkey,則首先從high所指向位置向前搜尋找到第一個關鍵字小於pivotkey的記錄和樞軸的記錄交換,然後從low所指向的位置向後搜尋找到第一個關鍵字大於pivotkey的記錄和樞軸的記錄交換。
重複這兩步,直至low==high為止。(為什麼要附設兩個指標從兩邊開始呢?樞軸右邊的都是大於它的,那麼只要從右邊找到第一個小於樞軸的
和樞軸交換一下,那麼小於樞軸的記錄就到了樞軸的左邊。樞軸的左邊也是同樣道理)
    快排的實現用到遞迴。
**/
// 劃分 劃分操作的時間複雜度是O(n)
int mpartition(int msort[],int low,int high){
int pivotkey = msort[low];
int  tmp;
while(low < high){
    while(low < high&&msort[high]>=pivotkey) --high;
    tmp = msort[low];
    msort[low] = msort[high];
    msort[high] = tmp;
    while(low < high&&msort[low]<=pivotkey) ++low;
    tmp = msort[low];
    msort[low] = msort[high];
    msort[high] = tmp;
    }
    return low;
}
/*****上述劃分每一次交換需要進行3次記錄移動(賦值)的操作。而實際上,對樞軸記錄的賦值操作是多餘的,因為只有到了low==high時
此位置才是樞軸記錄的最後位置,因此只要在此位置給樞軸賦值即可。******/
int improve_mpartition(int msort[],int low,int high){
int pivotkey = msort[low];
int  tmp;
while(low < high){
    while(low < high&&msort[high]>=pivotkey) --high;
    msort[low] = msort[high];
    while(low < high&&msort[low]<=pivotkey) ++low;
    msort[high] = msort[low];
    }
    msort[low] = pivotkey;
    return low;
}
// 遞迴操作的時間複雜度是o(log n)
 void quickSort(int msort[],int low,int high){
    int pivotloc;
    /***遞迴的終止條件是待排序的子序列是一個序列(也就是(序列的左邊界)low<high(序列的右邊界))***/
    if(low < high){
        pivotloc = improve_mpartition(msort,low,high);
        quickSort(msort,low,pivotloc-1);
        quickSort(msort,pivotloc+1,high);
    }
 }


int main(){
    /**
    輸入n個數
    **/
    scanf("%d",&n);
    for(int i = 0; i < n;i++){
        scanf("%d",&dig[i]);
    }
    /****
    因為陣列作為引數無法實現值傳遞, 所以用迴圈將陣列實現複製
    ****/
    int m1sort[100],m2sort[100],m3sort[100],m4sort[100];
    for(int i = 0;i < n;i++){
    m1sort[i] = dig[i];m2sort[i] = dig[i];
    m3sort[i] = dig[i];m4sort[i] = dig[i];
   // m5sort[i] = dig[i];
    }
    /****1 (交換類) 氣泡排序*****/
    printf("氣泡排序\n");
   bubblingSort(m1sort,n);




    /****2 (插入類) 直接插入排序*****/
     printf("直接插入排序\n");
    insertSort(m2sort,n);


    /****3 (選擇類) 簡單選擇排序*****/
    printf("簡單選擇排序\n");
    selectSort(m3sort,n);


    /****4 (交換類) 快速排序*****/
    printf("快速排序\n");
    quickSort(m4sort,0,n-1);
     for(int i = 0;i < n;i++){
        printf("%d ",m4sort[i]);
    }


}</span></span></span>