引言
只要設計到數據,就會涉及到數據的排序問題,比如給你隨機給你五個整數 3,1,5,2,4 。讓你從小到大進行排序,那我們該怎樣纔是實現對這些整數的排序呢 ?
答案是多種多樣的,比如用插入排序、選擇排序、堆排序、歸併排序、快速排序等等,這些排序方法都可以實現對整數排序,而這篇文章要講的就是插入排序
本文將從以下幾個問題對插入排序進行分析和講解:
- 什麼是插入排序?
- 插入排序的大概過程是什麼?
- 怎樣用代碼實現插入排序?
- 插入排序的代碼詳解。
什麼是插入排序?
下面看百度百科對插入排序的定義:插入排序,一般也被稱爲直接插入排序。對於少量元素的排序,它是一個有效的算法 。插入排序是一種最簡單的排序方法,它的基本思想是將一個記錄插入到已經排好序的有序表中,從而一個新的、記錄數增1的有序表。在其實現過程使用雙層循環,外層循環對除了第一個元素之外的所有元素,內層循環對當前元素前面有序表進行待插入位置查找,並進行移動 。
簡單來說:就是在想有序的數組中插入一個值,並且插入之後的數組仍然是有效的,進行一次次的插入,知道最後排好序。
下面看一個動圖:
插入排序的大概過程是什麼?
下面拿一個例子說明選擇排序的大概過程。
插入排序的基本思想就是:往有序的序列中一次次插入值,直到排序完成
下面來說用插入排序對3,1,5,2,4進行排序(從小到大排序)
- 首先選定第一個數3爲有序序列,拿着第二個數1往前面那個有序序列中插入值,插入的方法是用要插入的1依次和有序序列的值比較(從有序序列的後面依次往前比較),知道發現一個數比這個要插入的1小或者要插入的數走到了有序序列的頭部爲止。
- 經比較發現發現1<3,那就把有序序列的3後移一個位置(注意不是1和3這倆數)。這時候走到了頭,那就把數字1放到頭部。這時候數組元素爲1,3,5,2,4
- 繼續拿着5去有序序列中比較,發現5>3,那就不用繼續比較了,因爲3前面的數肯定比3小。 這時候數組元素爲1,3,5,2,4
- 繼續拿着2去和有序序列比較,首先發現2<5,那就把5後移一個位置(注意是後移)。再用2和3比較,發現2<3,那就把3後移一個位置,繼續用2和1比較,發現1<2。那就找到了放2的位置,把2在1後面就可以了。 只是後數組元素爲1,2,3,5,4
- 按照上面的方法,用4去一一比較即可,最後得到的結果就是1,2,3,4,5
總結:假設有n個數需要排序,我們可以默認第一數是有序的,那就只需n-1輪就可以排序完成。每輪就是拿着元素去有序序列從後往前比較,這可以寫一個while循環實現,循環結束的條件就是比較到頭了或者找了比這個數要小的數,
擴展:這個擴展對後面理解希爾排序特別有用, 如果暫時不理解這個擴展的也沒事。
- 就上我們上面第3步結束後,數組元素爲1,3,5,2,4,前三個元素爲有序序列,後兩個還未比較,這時候我們需要拿着2去比較,等比較結束,發現3和5都後移了一個位置,所以一共後移了兩個位置。
- 再看我們上面的的第4步結束後,數組 元素爲1,2,3,5,4。這時候還剩一個元素4沒有排序,排序後,發現5後移了一個位置,所以一共後移了一次。
- 一個是後移了兩次,一個是後移了一次,那麼時間複雜度肯定是不同的,後移一次的肯定更省時一些,而且後移的次數時候數組元素的 “ 相對有序 ” 有關。
- 相對有序的意思就是相對來說小元素在前面,大元素在後面,只要有這個意識就可以了,其他的就不再多贅述了。至於怎樣利用這個相對有序來減少排序的時間,就是後面希爾排序的事情了。
怎樣用代碼實現插入排序?
通過上面對3,1,5,2,4的排序過程講解,我們需要明確已知的三個條件
- 我們要排序的數組有哪些數?數組長度爲多少?
- 我們要進行幾輪插入操作?
- 每輪插入,哪些元素需要後移?
搞清楚了上面三個條件,我們下面我們動圖數據排序的實現代碼:
#include<iostream> using namespace std; //插入排序函數 穩定 void InsertionSort(int arr[],int len) { int temp; for(int i=1;i<len;i++) { int index=i-1;//前i-1個數已經排序好了 int current=arr[i]; while(index>=0&&arr[index]>current) { arr[index+1]=arr[index]; index--; } arr[index+1]=current; } } //輸出數組的值 void printf(int arr[],int len) { for(int i=0;i<len;i++) cout<<arr[i]<<" "; cout<<endl; } int main() { //要排序的數組 int arr[]={3, 44,38, 5,47,15,36,26,27,2 ,46,4 ,19,50,48}; int len=15;//要排序的數組長度 //排序 InsertionSort(arr,len); //輸出 printf(arr,len); return 0; }
運行結果:
插入排序的代碼詳解
- 上面代碼寫了兩個函數,一個是printf函數,這個是輸出排序後的數組。
- 另一個函數就InsertionSort函數,在這個函數裏面有一個二重循環,外層循環的的次數就是要查找的次數,內層循環的次數的就是要比較的次數,剛好對應上面說的(這裏數組下標是從0開始的)。如果對上面代碼有疑問,自己可以按照前面的過程,模擬一邊對3,1,4,5,2的排序過程,就知道代碼是怎樣執行的了 。
本文參考以及引用: