直接插入算法:每趟將一個待排序的關鍵字按照其值的大小插入到已經排好的部分有序序列的適當位置上,直到全部待排序的關鍵字都被插入到有序序列中爲止。前端
理論上,在直接插入排序中第二層循環是能夠提早結束的,即某個元素在尋找本身合適位置時並未循環遍歷到序列最前端。ios
這是直接插入排序和簡單選擇排序最大的不一樣。也是直接插入排序和簡單選擇排序同爲時間複雜度O(n2),可是直接插入排序效率更高的緣由。算法
尤爲是在待排序數據基本有序的時候,這種優點將極其明顯。甚至此時直接插入排序要比時間複雜度爲O(nlogn)的排序算法更加高效。數組
#include<iostream> #include<string> using namespace std; template <typename T> void insertSelectionSort(T arr[],int n){ //不用考慮第0個元素,由於插入排序初始狀況下,第0個元素自身就是有序的 for(int i=1;i<n;i++){ //尋找arr[i]合適的插入位置 //每次比較的是當前元素和當前元素的前一個元素的比較,故判斷條件是j>0而不是j>=0 for(int j=i;j>0&&arr[j-1]>arr[j];j--) swap(arr[j],arr[j-1]); } } int main(){ int a[10]={10,9,8,7,6,5,4,3,2,1}; insertSelectionSort(a,10); for(int i=0;i<10;i++) cout<<a[i]<<" "; cout<<endl; float b[3]={3.3f,2.2f,1.1f}; insertSelectionSort(b,3); for(int j=0;j<3;j++) cout<<b[j]<<" "; cout<<endl; string c[4]={"D","C","B","A"}; insertSelectionSort(c,4); for(int k=0;k<4;k++) cout<<c[k]<<" "; cout<<endl; return 0; }
輸出結果:函數
可是,若是咱們進行算法性能測試,咱們會發現上面的代碼並未將這種效率高的優點顯示出來。性能
緣由是在這段代碼中存在大量的數值交換,而每一次數值交換都包括三次賦值的操做,在本例中還包括訪問數組索引所在位置的時間,這些是比簡單的比較耗時更多的存在。測試
因此咱們能夠對上面關鍵代碼進行優化。優化
template <typename T> void insertSelectionSort(T arr[],int n){ for(int i=1;i<n;i++){ //將待排序的關鍵字複製出來,拿它與它前面的元素進行比較 T e=arr[i]; //須要把j的定義拿到for循環的外面,由於最後要在索引j指定的位置(比較後的目標位置)插入複製出來的關鍵字e int j; for(j=i;j>0&&arr[j-1]>e;j--) //將比待排序關鍵字的大的關鍵字依次後移 arr[j]=arr[j-1]; arr[j]=e; } }
在這裏咱們再也不調用swap函數進行數值的交換,而是全都是用賦值語句完成相應的操做。spa
就大大優化了算法。code
須要說明一下的是:對於直接插入排序,一趟排序後並不能確保一個關鍵字到達其最終位置。