1. 程式人生 > >淺談直接插入排序演算法思想以及時間複雜度分析

淺談直接插入排序演算法思想以及時間複雜度分析

研究意義

直接插入排序是最基本的一種排序演算法,其思想簡單,容易掌握,對後期的學習也有一定的幫助。

必備知識(之後不再敘述)

排序:將一組雜亂無章的資料排列成一個按關鍵字有序的序列。

穩定性:關鍵值相同的記錄,排序前後的相對次序不變。
    排序前:  15 1 4 3 4
    排序後:   1 3 4 4 15   穩定排序
                      1 3 4 4 15  不穩定排序 

內排序與外排序:內排序是指記錄集全部在記憶體中 ;外排序是指記錄集部分在記憶體中,排序過程中,需訪問外存 。

時間複雜度:   排序的時間複雜度可用演算法執行中的資料比較次數資料移動次數

來衡量。後面一般都按平均情況進行估算。對於那些受物件關鍵字序列初始排列及物件個數影響較大的,需要按最好情況和最壞情況進行估算。

空間複雜度:排序過程中需要使用的輔助儲存空間。

等差數列 前n項和公式:Sn=na1+n(n-1)d/2或Sn=n(a1+an)/2 

主要內容:

一、演算法思路(直接插入到已經有序的序列中)

設已存在一個有序子序列;每趟將一個記錄按關鍵值大小插入到有序子序列中。初始化時,有序子序列只有一個記錄。

直接插入排序就可以看作在一個只有一個元素的陣列中插入資料,每一次插入都插入到合適位置。插入時前面的序列已經有序,讓我們來模擬一下直接插入排序的方法。

假設我們拿到的資料是   5,7,3,8,2而手工排序的思路是 5  然後比較7和5的大小 ,合併為5,,7, 再在已經有序的5,7序列中插入3變為3,5,7,以此類推。

       完整的排序思路      5,7,3,8,2   (初始狀態)

                5,7,3,8,2

                                      3,5,7,8,2

                                      3,5,7,8,2

                                      2,3,5,7,8 (排序結束)

紅色標記的數字為每一次需要排序的數字(需要插入的數字).

二、實現程式碼

#include <stdio.h>
#include <stdlib.h>
//直接插入排序
int main()
{
    int a[10]={0,5,7,3,8,2,4,15,18,21};
    int i=0,j=0,k=0;
    printf("排序前的資料為:");
    for(k=1;k<10;k++)
    {
        printf("%3d",a[k]);
    }
    printf("\n");
    for(i=2;i<10;i++)
    {
        a[0]=a[i];  //a[0]為監視哨兵
        for(j=i-1;a[0]<a[j];j--)
        {
            a[j+1]=a[j]; //資料移動移動
        }
        a[j+1]=a[0];//插入到正確位置
    }
    printf("排序後的資料為:");
    for(k=1;k<10;k++)
    {
        printf("%3d",a[k]);
    }
    return 0;
}


注意:監視哨的作用:儲存副本,避免陣列下標越界。

三、演算法分析

一個記錄的輔助儲存空間 -----監視哨

當問題規模為n時

最好情況(原本就是有序的)
比較次數:Cmin=n-1
移動次數:Mmin=0

最差情況(逆序)

比較次數:Cmax=2+3+4+……+n=(n+2)n/2
移動次數:Mmax=1+2+3+……+n-1=n*n/2

若待排序物件序列中出現各種可能排列的概率相同,則可取上述最好情況和最壞情況的平均情況。在平均情況下的關鍵字比較次數和物件移動次數約為 n^2/4。因此,直接插入排序的時間複雜度為 o(n^2)。
另外直接插入排序是一種穩定的排序方法。