插入排序,顧名思義其實現形式是插入.
在整個大小不一的隊列中, 第一次: 從一個元素開始,將後面相鄰的元素(第二個元素)提取出來,放在一個變量中暫時保存,然後和第二個元素前面的那個元素(第一個元素)做比較,如果比它大,當然就不變動位置;但如果比它小,就將前面那個元素移動到第二個元素的位置,然後將變量的元素插入放在第一個元素的位置;
第二次: 從第二個元素開始將後面相鄰的元素(第三個元素)提取出來,放在之前那個變量中暫時保存,然後和第三個元素前面的那個元素(第二個元素)做比較,如果比它小,就將前面那個元素移動到第三個元素的位置, 接着再去對比更前一個的元素(第一個元素),如果比它小,就把那更前一個的元素(第一個元素)又移動到第二個元素的位置,然後將變量中的元素插入放在第一個元素的位置. 這樣這三個元素就依次是從小到大的排序.
重複第二次的操作,直到最後,整個插入排序處理結果 -- 隊列是按照從小到大的順序排列的. 複雜度爲 O(n^2).
明白了原理就不難實現了,下面用C++當練習實現了:
第一次做的時候,沒多想就這麼做了:
void insertSort()
{
int values[] = {4,8,7,11,2,25,27,18,1};
int ele; //記錄每次排序時當前的插入值
int length = 9;
cout << "The initial data is: " << endl;
print(values, length);
cout << "------------------------------" << endl;
for(int i=0;i<length-1;i++)
{
ele = values[i+1];
if(values[i+1] < values[i])
{ //後面的數比前一個數要小,則進行插入排序
for(int p=i;p>=0;p--)
{
if(ele < values[p])
{
values[p+1] = values[p];
values[p] = ele;
}
cout << "The test is: " << endl;
print(values, length);
cout << "------------------------------" << endl;
}
}
}
cout << "The result is: " << endl;
print(values, length);
cout << "------------------------------" << endl;
}
結果是對的,但是感覺實現過程繁瑣了.
接着看看,將第一個for循環的參數起點換爲1,將判斷也精簡到第二個for循環裏面, 出來的效果也是對的. 而代碼的精簡效果也立竿見影.看來不能忽視細節!!
第二次實現改了下變成這樣:
void newInsertSort()
{
int values[] = {4,8,7,11,2,25,27,18,1};
int ele; //記錄每次排序時當前的插入值
int length = 9;
cout << "The initial data is: " << endl;
print(values, length);
cout << "------------------------------" << endl;
for(int i=1;i<length;i++)
{
for(int p=i;p>0;p--)
{
if(values[p] < values[p-1])
{
ele = values[p];
values[p] = values[p-1];
values[p-1] = ele;
}
cout << "The test is: " << endl;
print(values, length);
cout << "------------------------------" << endl;
}
}
cout << "The result is: " << endl;
print(values, length);
cout << "------------------------------" << endl;
}
最後結果是一樣的.
有點感慨,很多人都有這樣的時候, 代碼寫久了容易麻木.而且可能當你身體很累很疲乏的時候就會退而求其次趕緊實現功能算了,不很會想去如何實現精簡高效的代碼.但其實注重下細節,哪怕一個參數的改變,也可能帶來截然不同的效果.看來算法是應該多練習,溫故知新.