插入排序
第一種:交換法
| 8 | 6 | 3 | 2 | 10 | 9 | 11 | 4 | 5 |
第一個元素就不需要考慮了,直接看第二個元素6,因為6<8,所以6與8交換位置得到:
| 6 | 8 | 3 | 2 | 10 | 9 | 11 | 4 | 5 |
在考慮第三個元素3,因為3<8,交換3和8,再比較3和6因為3<6,交換3和6得到:
| 3 | 6 | 8 | 2 | 10 | 9 | 11 | 4 | 5 |
后面以此類推
第二種:復制法:
|51|6|85|6|8|5|4|
| | 6|
將6復制一份,然后比較6之前的元素51
因為6<51,不適合放到當前位置,所以將51向后移動 ,考慮6是不是應該放到前一個位置
|51|51|85|6|8|5|4|
|6 |
因為現在6已經是第0個位置了,所以就放到這個位置。。。。以此類推
和上一個博客一樣,將之前的選擇排序寫到一個 .h 文件中來測試:
測試代碼:
1 #ifndef INC_04_INSERTION_SORT_SORTTESTHELPER_H 2 #define INC_04_INSERTION_SORT_SORTTESTHELPER_H 3 #include <iostream> 4 #include <algorithm> 5 #include <string> 6 #include <ctime> 7 #include <cassert> 8 using namespace std; 9 namespace SortTestHelper { 10 // 生成有n個元素的隨機數組,每個元素的隨機范圍為[rangeL, rangeR] 11 int *generateRandomArray(int n, int range_l, int range_r) { 12 int *arr = new int[n]; 13 srand(time(NULL)); 14 for (int i = 0; i < n; i++) 15 arr[i] = rand() % (range_r - range_l + 1) + range_l; 16 return arr; 17 } 18 // 拷貝整型數組a中的所有元素到一個新的數組, 並返回新的數組 19 int *copyIntArray(int a[], int n){ 20 int *arr = new int[n]; 21 copy(a, a+n, arr); 22 return arr; 23 } 24 // 打印arr數組的所有內容 25 template<typename T> 26 void printArray(T arr[], int n) { 27 for (int i = 0; i < n; i++) 28 cout << arr[i] << " "; 29 cout << endl; 30 return; 31 } 32 // 判斷arr數組是否有序 33 template<typename T> 34 bool isSorted(T arr[], int n) { 35 36 for (int i = 0; i < n - 1; i++) 37 if (arr[i] > arr[i + 1]) 38 return false; 39 return true; 40 } 41 // 測試sort排序算法排序arr數組所得到結果的正確性和算法運行時間 42 template<typename T> 43 void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) { 44 clock_t startTime = clock(); 45 sort(arr, n); 46 clock_t endTime = clock(); 47 cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl; 48 assert(isSorted(arr, n)); 49 return; 50 } 51 }; 52 53 #endif
選擇排序代碼:
1 #ifndef INC_04_INSERTION_SORT_SELECTIONSORT_H 2 #define INC_04_INSERTION_SORT_SELECTIONSORT_H 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 template<typename T> 7 void selectionSort(T arr[], int n){ 8 for(int i = 0 ; i < n ; i ++){ 9 int minIndex = i; 10 for( int j = i + 1 ; j < n ; j ++ ) 11 if( arr[j] < arr[minIndex] ) 12 minIndex = j; 13 swap( arr[i] , arr[minIndex] ); 14 } 15 } 16 #endif
插入函數(主函數)代碼
#include <iostream> #include <algorithm> #include "SortTestHelper.h" #include "SelectionSort.h" using namespace std; //一,沒有優化的插入排序(交換法) /* template<typename T> void insertionSort(T arr[], int n){ //插入排序第一個元素不用考慮 for( int i = 1 ; i < n ; i ++ ) { // 尋找元素arr[i]合適的插入位置 // 寫法一: // for( int j = i ; j > 0 ; j-- ) // if( arr[j] < arr[j-1] ) // swap( arr[j] , arr[j-1] ); // else // break; // 寫法二 : for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- ) swap( arr[j] , arr[j-1] ); } return; } */ //二,優化后的插入排序 (復制法) //51,6,85,6,8,5,4 // 6 //將6復制一份,然后比較6之前的元素51 //因為6<51,不適合放到當前位置,所以將51向后移動 ,考慮6是不是應該放到前一個位置 //51,51,85,6,8,5,4 //6 //因為現在6已經是第0個位置了,所以就放到這個位置。。。。以此類推 //寫法三 : template<typename T> void insertionSort(T arr[], int n){ for( int i = 1 ; i < n ; i ++ ) { // 尋找元素arr[i]合適的插入位置 T e = arr[i]; int j;//保存元素e應該插入的位置 for( j = i ; j > 0 && arr[j-1] > e ; j -- ){ arr[j] = arr[j-1]; } arr[j] = e; } } // 比較SelectionSort和InsertionSort兩種排序算法的性能效率 // 此時, 插入排序比選擇排序性能略低 int main() { int n = 20000; cout<<"Test for random array, size = "<<n<<", random range [0, "<<n<<"]"<<endl; int *arr1 = SortTestHelper::generateRandomArray(n,0,3); int *arr2 = SortTestHelper::copyIntArray(arr1, n); SortTestHelper::testSort("Insertion Sort", insertionSort,arr1,n); SortTestHelper::testSort("Selection Sort", selectionSort,arr2,n); delete[] arr1; delete[] arr2; cout<<endl; return 0; }
進行測試:
1.首先看一下沒有進行優化的[寫法一:]插入排序和選擇排序性能比較:
2.然后是沒有進行優化的[寫法二:]插入排序和選擇排序性能比較:
可見雖然性能都差不多,但是寫法二明顯比寫法一的代碼更漂亮
結論:在隨機的,無序的情況下,即是插入排序沒有優化但是它的性能依然比選擇排序好
3.優化后的插入排序與選擇排序比較:
可見此時插入排序的性能遠遠大於選擇排序