選擇排序和插入排序
選擇排序
選擇排序的思想非常簡單,很多書或技術Blog都講的很好,這裏不贅述了,直接給出代碼
1 void selectionSort(int arr[],int n){ 2 for(int i = 0;i<n;i++){ 3 int minIdx = i; 4 for(int j = i+1;j<n;j++){ 5 if(arr[j]<arr[minIdx]) 6 minIdx = j; 7 } 8 swap(arr[i],arr[minIdx]);9 } 10 }
如果考慮通用性,可以使用模板函數
1 template<typename T> 2 void selectionSort(T arr[],int n){ 3 for(int i = 0;i<n;i++){ 4 int minIdx = i; 5 for(int j = i+1;j<n;j++) 6 if(arr[j]<arr[minIdx]) 7 minIdx = j; 8 swap(arr[i],arr[minIdx]);9 } 10 }
插入排序
插入排序的思想非常簡單,無論是經典教材《算法導論》還是不少技術文章都以撲克牌為例,手裏的牌是有序的,每拿到一張新牌會為它在排好序的牌中找出合適的位置插入。
代碼如下:
1 void insertion_sort(int arr[],int n){ 2 for(int i =1;i<n;i++){ 3 for(int j = i+1;j<n-1;j++){ 4 if(arr[j+1]<arr[j]) 5 swap(arr[j],arr[j+1]); 6 else 7 break; 8 } 9 } 10 return; 11 }
對比選擇排序,雖然都是O(N^2)級別的,但是,我們發現,插入排序可以提前結束退出,所以理論上講插入排序應該比選擇排序快,這裏,可以寫個測試測試一下。測試結果,發現,比選擇排序慢,仔細觀察,我們發現,在第二層循環中,每當出現逆序(比較操作)就swap(),swap()函數的實現,我們在大學剛學習高級語言程序設計時應該就學過,它需要一個臨時變量,三句實現,需要花費三倍於比較時間。對於數組來說,還有訪問操作,那能不能改進插入排序算法,使之在第二層循環中只交換一次呢。當然,答案是可以的。
首先,我們把要考查的當前元素復制一份,接著將該元素副本與已排好序的元素比較,只要比當前元素大,就後移,最終不再移動的位置就應該是當前要考察元素的位置,等有時間了,我會把這段思考過程用圖片的形式演示出來,下面先放上代碼
1 void insertion_sort_opti(int arr[],int n){ 2 for(int i = 0;i<n;i++){ 3 int cur = arr[i] // copy the current element 4 int j;//define j,j is the aultimate index of the curr 5 for(int j = i;j>0&& arr[j-1]>cur;j--){ 6 arr[j] = arr[j-1]; 7 } 8 arr[j] = cur; 9 } 10 return; 11 }
希爾排序
之所以把希爾排序列在這裏,是因為希爾排序也是一種插入排序,希爾排序整體的思路就是插入排序的延伸,在插入排序中,每一次都和之前的一個元素進行比較,而希爾排序是每一次都和之前的第h個元素進行比較,h從一個很大的值逐漸減小為1,一步步將一個完全無序的數組變成一個近乎有序的數組,變成有序性越來越強的數組,直到最後變成一個有序的數組,不難理解,希爾排序會更高效,因為插入排序對於有序數組的可以達到線性的時間復雜度,既然是插入排序的延伸,依然給出未優化的和優化的版本,實現如下:
V1
1 void shell_sort(int arr[],int n){ 2 int h = 1;//make sure the last step h =1 3 while(h*3<n) h = h*3+1; 4 while(h>=1){ 5 // like to insertion sort,start with teh second element 6 for(int i = 1;i<n;i++){ 7 for(int j = i;j>=h;j-=h){ //j starts with current(i-th) 8 if(arr[j]<arr[j-h]) //element,compare with (j-h)th 9 swap(arr[j],arr[j-h]); //element,if less than 10 else // swap 11 break; 12 } 13 } 14 h/=3; 15 } 16 }
優化版本
1 void shell_sort_opti(int arr[],int n){ 2 int h = 1; 3 while(h<n/3) h = h*3+1; 4 while(h>=1){ 5 for(int i = 1;i<n;i++){ 6 int curr = arr[i]; 7 int j; 8 for(j = i;j>=h;j-=h) 9 if(arr[j]<curr) 10 arr[j] = arr[j-h]; 11 arr[j] = curr; 12 } 13 h/=3; 14 } 15 }
選擇排序和插入排序