排序算法之直接插入排序
排序算法分為很多種,其中插入排序算是最基礎的排序算法了。插入排序包括直接插入排序,折半插入排序和希爾排序,這三種排序算法本質是一樣的,但是在實際操作和實現的過程中有不同的輔助存儲空間和時間復雜度。
一、直接插入排序
基本思想
直接插入排序是指把一個元素直接插入到一個有序表中,從而得到一個元素數增加1的新有序表。所以當需要排序一組數時,我們取出這組數的第1個元素作為一個有序表,然後取第2個元素進行插入,得到一個含有2個元素的有序表,再取第3個元素進行插入,以此類推,直到最後一個元素被插入到新的有序表中,排序完成。
在一個已有i個元素的有序表中插入新元素時,可以選擇從第i個元素開始從後往前搜索新元素插入的位置,這樣就可以在搜索的過程中後移元素,以便在找到插入的位置時直接將新元素插入(見偽代碼)。也可以在從後往前搜索的過程中,當插入的元素小於與其比較的元素時,直接原地交換,然後繼續向前搜索,直到跳出循環(見下文代碼實現)。原地交換的好處就是節省一些空間,並且可以防止數組越界。
舉個栗子
需要排序的數列為:22 45 12 47 56 36
第一次: (22 45)12 47 56 36
第二次: (12 22 45)47 56 36
第三次: (12 22 45 47)56 36
第三次: (12 22 45 47 56)36
第四次: (12 22 36 45 47 56) 排序完成!
算法偽代碼
InsertionSort(A[0...n-1]) //用插入排序對給定數組排序 //輸入:n個可排序元素構成的一個數組A[0...n-1] //輸出:非降序排列的數組A[0...n-1] for i ← 1 to n-1 do v ← A[i] j ← i-1 while j >= 0 and A[j]>v do A[j+1] ← A[j] //後移元素 j ← j+1 A[j+1] ← v
算法復雜度分析
由上面的偽代碼可以看出,該算法的基本操作是鍵值比較 A[j]>v,顯然鍵值比較的次數顯然依賴於特定的輸入。在最壞的情況下,上述偽代碼的while循環每次都從j=i-1執行到j=0,也就是說原數組是一個降序排列的數組,所以對於這種輸入,鍵值的比較次數是:
C worst(n)= ∑(i=1...n-1)∑(j=0...i-1) 1= (n-1)n/2 ∈ θ(n^2)
最好的情況下,原數組已經按照升序排列了,所以每次while循環只執行一次,故對於n個元素的數組鍵值比較次數為n ∈ θ(n),但是這種情況本身沒有多大意義,因為我們不能指望有這麽簡單的輸入。
根據書上所講的,對於隨機序列的數組,直接插入排序的平均比較次數是降序數組的一半,也就是說:
C avg(n)= (n-1)n/4 ∈ θ(n^2)
平均性能比最差性能快一倍,並且在遇到基本有序數組時表現優異,使得直接插入排序領先於它在基本排序算法領域的主要競爭對手——選擇排序和冒泡排序,但這並不意味著它可以取代這些算法,接下來的文章中我會再溫習這些算法。
算法的代碼實現(Java)
public class InsertionSort { public static void main(String[] args){ int [] array=new int[]{22,65,34,18,56,49,0}; int temp; for(int i=1;i<array.length;i++){ for(int j = i;j > 0;j--){ if(array[j] < array[j-1]){ temp = array[j-1]; array[j-1] = array[j]; array[j] = temp; } } } for(int i:array) System.out.print(i+","); } }
水平有限,希望諸位大佬多加指正!
本文出自 “衛莨” 博客,轉載請與作者聯系!
排序算法之直接插入排序