插入排序-C實現中的幾點問題記錄

來源:互聯網
上載者:User

昨晚看《演算法導論》,其中有一個舉例是插入排序。上午我用C語言實現了該演算法。本來以為自己理解了昨晚所看的演算法,誰知實現的時候還是出現了些問題。我們在學習時會遇到這樣的現象:你以為自己會了,潛意識裡認為只要懂了原理花些時間就可以搞定。所以我們看書時大多隻關注原理。這樣本身也沒有什麼不好,因為人的大腦有限,每天思考也不能過於長,否則容易分神。而記住原理忽略細節可以是大腦的一種自我保護機制。同時這也是一個陷阱,我們時常以為自己理解了卻沒有驗證這種理解,這種理解往往在運用時會出現一些問題,顯得不太可靠。

第一次實現

經過思考,我用C語言實現了插入排序:

#include "stdafx.h"#define SIZE 7void PrintNewLine();void PrintArray(int arr[]);void InsertionSort(int arr[]);int _tmain(int argc, _TCHAR* argv[]){int original[] = {2,5,3,1,4,7,6};PrintArray(original);PrintNewLine();InsertionSort(original);PrintNewLine();PrintArray(original);char wait = getchar();return 0;}void PrintArray(int arr[]){for(int i = 0; i < SIZE; i++)printf("%d ",arr[i]);printf("\n");}void PrintNewLine(){printf("\n");}void InsertionSort(int arr[]){for(int i=1; i < SIZE; i++){int key = arr[i];while(key < arr[i-1] && i > 0)    //i>0 role as Termination{//Exchage key and element which postion at key-1arr[i] = arr[i-1];arr[i-1] = key;//Due to key advanced, so key's previous element will be compared next.i--;}PrintArray(arr);}}

輸出如下:

2 5 3 1 4 7 62 5 3 1 4 7 62 3 5 1 4 7 62 3 5 1 4 7 61 2 3 5 4 7 61 2 3 5 4 7 61 2 3 5 4 7 61 2 3 5 4 7 61 2 3 4 5 7 61 2 3 4 5 7 61 2 3 4 5 7 61 2 3 4 5 6 71 2 3 4 5 6 71 2 3 4 5 6 7

 

問題

通過每次迭代的結果可知,上面的InsertionSort方法中有一個缺陷。演算法的迭代次數遠遠超出了預計。導致這個原因的是:我們在內層while迴圈中對迭代子i的操作,影響到外層的for迴圈中的i取值。這樣每次迭代外層迴圈都是從下標1開始。而從下標1開始會重複迭代那些已經排序好的元素。

其實簡單些講,這個是常見編程陷阱即:命名衝突(Naming Conflict)

 

第二次實現

要解決這個問題,並不是很難,我們引入一個內層while迴圈專用的迭代子j,代碼如下:

void InsertionSort(int arr[]){for(int i=1; i < SIZE; i++){int key = arr[i];int j = i;while(key < arr[j-1] && j > 0)    //i>0 role as Termination{//Exchage key and element which postion at key-1arr[j] = arr[j-1];arr[j-1] = key;//Due to key advanced, so key's previous element will be compared next.j--;}PrintArray(arr);}}

輸出如下:

2 5 3 1 4 7 62 5 3 1 4 7 62 3 5 1 4 7 61 2 3 5 4 7 61 2 3 4 5 7 61 2 3 4 5 7 61 2 3 4 5 6 71 2 3 4 5 6 7

 

問題

由輸出我們可以看見,命名衝突問題已經解決。我們外層迴圈一共執行了n-1次(n為需排序元素個數,此處為7)。但這個實現跟演算法導論上的實現還是有一些不同。我的實現將每次待排序的元素Key跟Key前面的元素進行交換。而演算法導論上的實現更加嚴謹:先移動元素,待元素移動好了,再將Key插入適當的位置。

每次都移動Key並不是必要的,必要的移動只是最後一步,即:將Key移動到適當的位置。

這個在實現上的區別就是將一條語句從內層迴圈移動至外層迴圈。

 

第三次實現
void InsertionSort(int arr[]){for(int i=1; i < SIZE; i++){int key = arr[i];int j = i;while(key < arr[j-1] && j > 0)    //i>0 role as Termination{//move key to previous positionarr[j] = arr[j-1];j--;}arr[j] = key;   /*將key的賦值從內層迴圈移動至外層迴圈*/PrintArray(arr);}}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.