撲克牌是我們幾乎每個人都可能從事過的遊戲。而最基本的撲克玩法都是一邊摸牌,一邊理牌。假如我們拿到了這樣一手牌,如圖9-5-1。啊,似乎是同花順呀,別急,我們得理一理順序才知道是否是真的同花順。請問,如果是你,應該如何理牌呢?
應該說,哪怕你是第一次玩撲克牌,只要認識這些數字,理牌的方法都是不用教的。將3和4移動到5的左側,再將2移動到最左側,順序就算是理好了。這裡,我們的理牌方法,就是直接插入排序法。
直接插入排序(straight insertion sort)的基本操作是將乙個記錄插入到已經排好序的有序表中,從而得到乙個新的、記錄數增1的有序表。
顧名思義,從名稱上也可以知道它是一種插入排序的方法。我們來看直接插入排序法的**。(注:要了解演算法的原理,直接看**和後面的解釋並不是最好的辦法。將**輸入到電腦中,執行並斷點逐行跟蹤,參照本文的講解和圖示,觀察變數的變化情況,才會收到比較好的效果。這裡的**全是用c語言編寫,不過對於擅長c#的讀者應該不存在閱讀難度。)
void
insertsort(sqlist *l)
213}14
} 1) 程式開始執行,此時我們傳入的sqlist引數的值為length=6,r[6]=,其中r[0]=0將用於後面起到哨兵的作用。
2) 第4~13行就是排序的主迴圈。i從2開始的意思是我們我們假設r[1]=5已經放好位置,後面的牌其實就是插入到它的左側還是右側的問題。
3) 第6行,此時i=2,l.r[i]=3比l.r[i-1]=5要小,因此執行第8~11行的操作。第8行,我們將l.r[0]賦值為l.r[i]=3的目的是為了起到第9~10行的迴圈終止的判斷依據。如圖9-5-2。圖中下方的虛線箭頭,就是第10行,l.r[j-1]=l.r[j]的過程,將5右移一位。
4) 此時,第10行就是在移動完成後,空出了空位,然後第11 行l.r[j+1]=l.r[0],將哨兵的3賦值給j=0時的l.r[j+1],也就是說,將撲克牌3放放置到l.r[1]的位置。如圖9-5-3。
5) 繼續迴圈,第6行,因為此時i=3,l.r[i]=4比l.r[i-1]=5要小,因此執行第8~11行的操作。將5再右移一位,將4放置到當前5所在位置。如圖9-5-4。
6) 再次迴圈,此時i=4。因為l.r[i]=6比l.r[i-1]=5要大,於是第8~11行**不執行,此時前三張牌的位置沒有變化。如圖9-5-5。
7) 再次迴圈,此時i=5,因為l.r[i]=2比l.r[i-1]=6要小,因此執行第8~11行的操作。由於6、5、4、3都比2小,它們都將右移一位,將2放置到當前3所在位置。如圖9-5-6。此時我們的排序也就完成了。
9.5.2 直接插入排序複雜度分析
我們來分析一下這個演算法,從空間上來看,它只需要乙個記錄的輔助空間。因此關鍵是看它的時間複雜度。
當最好的情況,也就是要排序的表本身就是有序的,比如紙牌拿到後就是,那麼我們比較次數,其實就是**第6行每個l.r[i]與l.r[i-1的比較,共比較了
當最壞的情況,即待排序表是逆序的情況比如,此時需要比較
如果排序記錄是隨機的,那麼根據概率相同的原則,平均比較和移動次約為n2/4 次。因此,我們得出直接插入排序法的時間複雜度為o(n2)。從這裡也看出,同樣的o(n2)時間複雜度,直接插入排序法比冒泡和簡單選擇排序的效能要好一些。
直接插入排序演算法
直接插入演算法 有乙個已經有序的資料序列,要求在這個已經排好的資料序列中插入乙個數,但要求插入後此資料序列仍然有序,這個時候就要用到一種新的排序方法 插入排序演算法,插入排序的基本操作就是將乙個資料插入到已經排好序的有序資料中,從而得到乙個新的 個數加一的有序資料,演算法適用於少量資料的排序,時間複...
直接插入排序演算法
每次將乙個待排序的記錄按其關鍵字的大小插到前面已經排序的序列中的適當位置,直到全部記錄插入完畢為止。第一趟比較前兩個數,然後把第二個數按大小插入到有序表中 第二趟把第三個資料與前兩個數從後向前掃瞄,把第三個數按大小插入到有序表中 依次進行下去,進行了 n 1 趟掃瞄以後就完成了整個排序過程。將待插入...
演算法 直接插入排序
一 總體思想 將乙個記錄直接插入到乙個已經排序好的列表中的對應位置,形成乙個新的列表。直接插入排序為穩定排序。二 排序過程 公升序 1 認為第乙個記錄為有序列表。2 從第二個記錄開始,依次和已經排序的列表中記錄做比較,如果被比較記錄大於該記錄,則將被比較記錄後移一位,否則將該記錄插入到不大於它的記錄...