排序演算法之插入排序

2022-02-06 09:05:31 字數 1485 閱讀 1312

想象一種現實場景,幾個人打撲克牌,在接牌過程中,假設按照撲克牌上的數字大小進行擺牌,假設手中已經有若干張撲克牌(按照牌面大小排好次序),那麼下次接到牌之後,我們會把剛接到的牌「插入」到手中已有的牌序列中的"合適"位置,現實中的這種"接牌"思路,就是我們今天要說的"插入思想"

給定乙個長度為n的序列l,如何用"接牌"思路把它排好序呢?我們知道,排序演算法涉及的兩個基本操作:比較和移動元素。如果序列l是陣列,我們會採用"就地排序"(in-place sort),即始終將序列l看做兩部分 sorted+unsorted l[0,r)+l[r,n),初始化時 |s|=r=0為空序列無所謂有序。在迭代過程中,關注並處理e=l[r],在s中確定適當位置(有序序列中查詢),插入e,得到有序序列l[0,r]。

演算法正確性證明

不變性:隨著r的遞增,l[0,r)始終有序,直到r=n,l即為整體有序。

單調性:初始時,問題規模為n,即無序區間長度為n,有序區間長度為0,隨著r的遞增,有序序列向右擴充套件,無序序列區間相應縮小(減治法策略),直至最終整體有序,滿足單調性

void insertionsort(int a, int lo, int hi)//插入排序 a[lo,hi)

a[j+1] = e;     //注意,位置j是不待遇e的最大秩,因此插入元素額要在j之後}}

演算法最好情況下,待排元素全部有序,這樣只需比較n-1次,每次比較之後,待插入元素e仍處在原來位置,無需移動元素,時間複雜度o(n),演算法最壞情況下,待排元素全部逆序,這樣在插入元素時,需要比較1+2+3+4+…+n-1=,同時移動元素次數也是,這樣時間複雜度為o(n2),平均複雜度也為o(n2)

由於在排序過程中,插入元素位置是滿足插入依然有序的,即嚴格意義的大於,所以插入排序演算法是穩定的排序演算法。

為了便於理解,可以將在有序向量中查詢不大於元素e的位置和插入元素e這兩個步驟分別編成函式,

void insertionsort_b(int a, int lo, int hi)//a[lo,hi)插入排序

}int search(int a, int e, int lo, int hi)   //在向量a[lo,hi)中查詢不大於元素e的最大秩並返回

我們看到,插入排序的時間複雜度不僅與問題的規模n有關,而且與輸入序列的逆序對總數i也息息相關,這種輸入敏感型演算法input-sensitive在排序演算法中有著特殊地位。從上面的有序向量查詢過程中,我們可以看到,insert(search(a,e)+1,e)這條語句仍然會保持有序向量a的有序性,這得益於我們的search每次返回的都是不大於e的最大秩,即使有序向量中有多個重複元素e,仍然會返回e的最大秩,這樣才保證插入不破壞有序性。

排序演算法之插入排序

排序演算法之插入排序 1 插入排序的思想 假設在乙個有序序列中 e 0 e i 1 這i 個元素已經排好序,則當要將第 i 1個元素 e 插入該序列時,只需將第 i 1個元素與從 e 0 開始到e i 1 元素進行比較,當發現第 j個元素 e j 在序列中應在 e 前,且 e j 1 應在e 後時,...

排序演算法之插入排序

排序演算法之插入排序 1 插入排序的思想 假設在乙個有序序列中 e 0 e i 1 這i 個元素已經排好序,則當要將第 i 1個元素 e 插入該序列時,只需將第 i 1個元素與從 e 0 開始到e i 1 元素進行比較,當發現第 j個元素 e j 在序列中應在 e 前,且 e j 1 應在e 後時,...

排序演算法之插入排序

本節主要分析插入排序演算法的直接插入排序和希爾 shell 排序 又稱縮小增量排序 1.直接插入排序 該排序是最簡單的排序方法,其基本思想是 假設待排序的記錄存放在陣列r 1.n 中。初始時,r 1 自成1個有序區,無序區為r 2.n 從i 2起直至i n為止,依次將r i 插入當前的有序區r 1....