1. 程式人生 > >排序算法系列之直接插入排序

排序算法系列之直接插入排序

直接插入排序

1 基本原理

1 核心思想:插入排序通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入 ,如此重複,直至完成序列排序。
2 演算法分析
1. 從序列第一個元素開始,該元素可以認為已經被排序
2. 取出下一個元素,設為待插入元素,在已經排序的元素序列中從後向前掃描,如果該元素(已排序)大於待插入元素,將該元素移到下一位置。
3. 重複步驟2,直到找到已排序的元素小於或者等於待排序元素的位置,插入元素
4. 重複2,3步驟,完成排序。

2 例項說明

如上圖所示,以一組資料{12,15,9,20,6,31,24} 為例,進行直接插入排序的演算法演示:

  1. 預設序列第一個元素12 以及被排序。
  2. 取下一元素 15 從後往前與已排序序列一次比較,15插入12 之後,已排序序列為[12,15]。
  3. 取下一元素9,重複2步驟,將9插12 之前,已排序序列為[9,12,15]。
  4. 迴圈上述操作,直至最後一個元素24,插入合適位置,完成排序。

3 程式碼實現

// 直接插入排序(C++)
void InsertSort(vector<int> &vi)
{
    for(int i=1;i<vi.size();i++) 
    {
        int temp=vi[i];
        int j;
        for
(j=i-1;j>=0&&temp<vi[j];j--) { vi[j+1]=vi[j]; //將較大元素後移 } vi[j+1]=temp; //temp插入正確的位置 } }

演算法改進:二分插入排序
二分查詢插入排序的原理:是直接插入排序的一個變種,區別是:在有序區中查詢新元素插入位置時,為了減少元素比較次數提高效率,採用二分查詢演算法進行插入位置的確定。

演算法分析:
設陣列為a[0…n]。
1. 將原序列分成有序區和無序區。a[0…i-1]為有序區,a[i…n] 為無序區。(i從1開始)
2. 從無序區中取出第一個元素,即a[i],使用二分查詢演算法在有序區中查詢要插入的位置索引j。
3. 將a[j]到a[i-1]的元素後移,並將a[i]賦值給a[j]。
4. 重複步驟2~3,直到無序區元素為0。

// 二分插入排序
void BinInsertSort(vector<int> &vi)
{
    for(int i=1;i<vi.size();i++)
    {
        int left=0;
        int right=i-1;
        int temp=vi[i]
        while(left<=right)
        {
            int mid=(left+right)/2; //二分割槽域
            if(vi[mid]>temp)
            {
                right=mid-1;       //向左縮小區域
            }
            else
            {
                left=mid+1;        //向右縮小區域
            }
        }

        for(int j=i-1;j>left;j--)  //vi[left,i-1]的元素整體後移
        {
            vi[j+1]=vi[j];
        }
        vi[left]=temp;
    }
}

4 效能分析

  • 1 時間複雜度
    (1)順序排列時,只需比較(n-1)次,插入排序時間複雜度為O(n)
    (2)逆序排序時,需比較n(n-1)/2次,插入排序時間複雜度為O(n^2)
    (3)當原始序列雜亂無序時,平均時間複雜度為O(n^2)
  • 2 空間複雜度
    插入排序過程中,需要一個臨時變數temp儲存待排序元素,因此空間複雜度為O(1)
  • 3 演算法穩定性
    插入排序是一種穩定的排序演算法