菜鳥必看的排序演算法(簡單通俗)及程式碼實現,幾張圖帶你吃透排序演算法

無憂程式設計師發表於2020-11-05

一、插入排序

插入排序演算法是所有排序方法中最簡單的一種演算法,其主要的實現思想是將資料按照一定的順序一個一個的插入到有序的表中,最終得到的序列就是已經排序好的資料。

直接插入排序是插入排序演算法中的一種,採用的方法是:在新增新的記錄時,使用順序查詢的方式找到其要插入的位置,然後將新記錄插入。

很多初學者所說的插入排序,實際上指的就是直接插入排序演算法,插入排序演算法還包括折半插入排序、2-路插入排序,表插入排序和希爾排序等,後序文章都會一一講到。

例如採用直接插入排序演算法將無序表{3,1,7,5,2,4,9,6}進行升序排序的過程為:

首先考慮記錄 3 ,由於插入排序剛開始,有序表中沒有任何記錄,所以 3 可以直接新增到有序表中,則有序表和無序表可以如圖 1 所示:
在這裡插入圖片描述

向有序表中插入記錄 1 時,同有序表中記錄 3 進行比較,1<3,所以插入到記錄 3 的左側,如圖 2 所示:
在這裡插入圖片描述

圖 2 直接插入排序(2)
向有序表插入記錄 7 時,同有序表中記錄 3 進行比較,3<7,所以插入到記錄 3 的右側,如圖 3 所示:
在這裡插入圖片描述

圖 3 直接插入排序(3)
向有序表中插入記錄 5 時,同有序表中記錄 7 進行比較,5<7,同時 5>3,所以插入到 3 和 7 中間,如圖 4 所示:
在這裡插入圖片描述

圖 4 直接插入排序(4)
向有序表插入記錄 2 時,同有序表中記錄 7進行比較,2<7,再同 5,3,1分別進行比較,最終確定 2 位於 1 和 3 中間,如圖 5 所示:
在這裡插入圖片描述

圖 5 直接插入排序(5)
照此規律,依次將無序表中的記錄 4,9 和 6插入到有序表中,如圖 6 所示:
在這裡插入圖片描述

圖 6 依次插入記錄4,9和6
直接插入排序的具體程式碼實現為:

#include <stdio.h>
//自定義的輸出函式
void print(int a[], int n ,int i){
    printf("%d:",i);
    for(int j=0; j<8; j++){
        printf("%d",a[j]);
    }
    printf("\n");
}
//直接插入排序函式
void InsertSort(int a[], int n)
{
    for(int i= 1; i<n; i++){
        if(a[i] < a[i-1]){//若第 i 個元素大於 i-1 元素則直接插入;反之,需要找到適當的插入位置後在插入。
            int j= i-1;
            int x = a[i];
            while(j>-1 && x < a[j]){  //採用順序查詢方式找到插入的位置,在查詢的同時,將陣列中的元素進行後移操作,給插入元素騰出空間
                a[j+1] = a[j];
                j--;
            }
            a[j+1] = x;      //插入到正確位置
        }
        print(a,n,i);//列印每次排序後的結果
    }
}
int main(){
    int a[8] = {3,1,7,5,2,4,9,6};
    InsertSort(a,8);
    return 0;
}

執行結果為:

1:13752496
2:13752496
3:13572496
4:12357496
5:12345796
6:12345796
7:12345679

直接插入排序演算法本身比較簡潔,容易實現,該演算法的時間複雜度為O(n2)。

在這裡插入圖片描述

關注UP長時間更新分享C/C++語言基礎等程式設計乾貨技術,工具安裝包和學習資料已備好。領取學習資料和視訊Q群:1070240985

資料內容包括:

2小時掌握《網際網路聊天室系統架構》 C/C++打造逆向工具《埠掃描神器》 IOCP高效能伺服器之《客戶端壓力測試系統》
C/C++打造簡易《TCP伺服器端》程式 2小時剖析C/C++程式設計精華《指標詳解》 面試官必考的《演算法設計之連結串列》
騰訊QQ之《極速檔案傳輸工具》 C、C++打造《伺服器設計模型》 C/C++開發《系統檔案瀏覽器工具》 C/C++開發《太空大戰遊戲》
手把手寫《憤怒的小鳥彈球》遊戲 等等…

免費報名直通車:這是一門真正適合任何零基礎學習的入門課,由教學經驗超過十年的大咖級老師講解。課程知識點通俗易懂,能夠將每一個知識點落地到實際案例。

二、氣泡排序
起泡排序,別名“氣泡排序”,該演算法的核心思想是將無序表中的所有記錄,通過兩兩比較關鍵字,得出升序序列或者降序序列。

例如,對無序表{49,38,65,97,76,13,27,49}進行升序排序的具體實現過程如圖 1 所示:

圖 1 第一次起泡
如圖 1 所示是對無序表的第一次起泡排序,最終將無序表中的最大值 97 找到並儲存在表的最後一個位置。具體實現過程為:

首先 49 和 38 比較,由於 38<49,所以兩者交換位置,即從(1)到(2)的轉變;
然後繼續下標為 1 的同下標為 2 的進行比較,由於 49<65,所以不移動位置,(3)中 65 同 97 比較得知,兩者也不需要移動位置;
直至(4),97 同 76 進行比較,76<97,兩者交換位置,如(5)所示;
同樣 97>13(5)、97>27(6)、97>49(7),所以經過一次氣泡排序,最終在無序表中找到一個最大值 97,第一次冒泡結束;

由於 97 已經判斷為最大值,所以第二次氣泡排序時就需要找出除 97 之外的無序表中的最大值,比較過程和第一次完全相同。

經過第二次冒泡,最終找到了除 97 之外的又一個最大值 76,比較過程完全一樣,這裡不再描述。

通過一趟趟的比較,一個個的“最大值”被找到並移動到相應位置,直到檢測到表中資料已經有序,或者比較次數等同於表中含有記錄的個數,排序結束,這就是起泡排序。
起泡排序的具體實現程式碼為:

#include <stdio.h>
//交換 a 和 b 的位置的函式
void swap(int *a, int *b);
int main()
{
    int array[8] = {49,38,65,97,76,13,27,49};
    int i, j;
    int key;
    //有多少記錄,就需要多少次冒泡,當比較過程,所有記錄都按照升序排列時,排序結束
    for (i = 0; i < 8; i++){
        key=0;//每次開始冒泡前,初始化 key 值為 0
        //每次起泡從下標為 0 開始,到 8-i 結束
        for (j = 0; j+1<8-i; j++){
            if (array[j] > array[j+1]){
                key=1;
                swap(&array[j], &array[j+1]);
            }
        }
        //如果 key 值為 0,表明表中記錄排序完成
        if (key==0) {
            break;
        }
    }
    for (i = 0; i < 8; i++){
        printf("%d ", array[i]);
    }
    return 0;
}
void swap(int *a, int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

執行結果為:

13 27 38 49 49 65 76 97

使用起泡排序演算法,其時間複雜度同實際表中資料的無序程度有關。若表中記錄本身為正序存放,則整個排序過程只需進行 n-1(n 為表中記錄的個數)次比較,且不需要移動記錄;若表中記錄為逆序存放(最壞的情況),則需要 n-1趟排序,進行 n(n-1)/2 次比較和資料的移動。所以該演算法的時間複雜度為O(n2)。
在這裡插入圖片描述

首先恭喜您,能夠認真的閱讀到這裡,如果對部分理解不太明白,建議先將文章收藏起來,然後對不清楚的知識點進行查閱,然後在進行閱讀,相應你會有更深的認知。如果您喜歡這篇文章,就點個贊或者【關注我】吧!!專案實戰直通車一起學習

相關文章