氣泡排序的實現和優化及其與插入,選擇排序的比較
阿新 • • 發佈:2018-12-07
備註:這裡使用的插入排序和選擇排序都是經過優化後的詳細優化請檢視上一條部落格,編譯器使用DEV-C++
氣泡排序演算法的運作如下:(從後往前)
1.比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
2.對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
3.針對所有的元素重複以上的步驟,除了最後一個。
4.持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較
測試程式碼:
1 #ifndef OPTIONAL_01_BUBBLE_SORT_SORTTESTHELPER_H 2 #defineOPTIONAL_01_BUBBLE_SORT_SORTTESTHELPER_H 3 #include <iostream> 4 #include <algorithm> 5 #include <ctime> 6 #include <string> 7 #include <cassert> 8 using namespace std; 9 namespace SortTestHelper { 10 // 生成有n個元素的隨機陣列,每個元素的隨機範圍為[rangeL, rangeR] 11 int *generateRandomArray(intn, 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 // 生成一個近乎有序的陣列 19 // 首先生成一個含有[0...n-1]的完全有序陣列, 之後隨機交換swapTimes對資料20 // swapTimes定義了陣列的無序程度 21 int *generateNearlyOrderedArray(int n, int swapTimes){ 22 int *arr = new int[n]; 23 for(int i = 0 ; i < n ; i ++ ) 24 arr[i] = i; 25 srand(time(NULL)); 26 for( int i = 0 ; i < swapTimes ; i ++ ){ 27 int posx = rand()%n; 28 int posy = rand()%n; 29 swap( arr[posx] , arr[posy] ); 30 } 31 return arr; 32 } 33 // 拷貝整型陣列a中的所有元素到一個新的陣列, 並返回新的陣列 34 int *copyIntArray(int a[], int n){ 35 int *arr = new int[n]; 36 copy(a, a+n, arr); 37 return arr; 38 } 39 // 列印arr陣列的所有內容 40 template<typename T> 41 void printArray(T arr[], int n) { 42 for (int i = 0; i < n; i++) 43 cout << arr[i] << " "; 44 cout << endl; 45 return; 46 } 47 // 判斷arr陣列是否有序 48 template<typename T> 49 bool isSorted(T arr[], int n) { 50 for (int i = 0; i < n - 1; i++) 51 if (arr[i] > arr[i + 1]) 52 return false; 53 return true; 54 } 55 // 測試sort排序演算法排序arr陣列所得到結果的正確性和演算法執行時間 56 template<typename T> 57 void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) { 58 clock_t startTime = clock(); 59 sort(arr, n); 60 clock_t endTime = clock(); 61 cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl; 62 assert(isSorted(arr, n)); 63 return; 64 } 65 }; 66 #endif
選擇排序程式碼:
1 #ifndef OPTIONAL_01_BUBBLE_SORT_SELECTIONSORT_H 2 #define OPTIONAL_01_BUBBLE_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
插入排序程式碼:
1 #ifndef OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H 2 #define OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 template<typename T> 7 void insertionSort(T arr[], int n){ 8 for( int i = 1 ; i < n ; i ++ ) { 9 T e = arr[i]; 10 int j; 11 for (j = i; j > 0 && arr[j-1] > e; j--) 12 arr[j] = arr[j-1]; 13 arr[j] = e; 14 } 15 return; 16 } 17 #endif
氣泡排序以及優化程式碼:
1 #include <iostream> 2 #include <algorithm> 3 #include "SortTestHelper.h" 4 #include "SelectionSort.h" 5 #include "InsertionSort.h" 6 using namespace std; 7 // 第一版bubbleSort 8 template<typename T> 9 void bubbleSort( T arr[] , int n){ 10 bool swapped; 11 do{ 12 swapped = false; 13 for( int i = 1 ; i < n ; i ++ ) 14 if( arr[i-1] > arr[i] ){ 15 swap( arr[i-1] , arr[i] ); 16 swapped = true; 17 } 18 // 優化, 每一趟Bubble Sort都將最大的元素放在了最後的位置 19 // 所以下一次排序, 最後的元素可以不再考慮 20 n --; 21 }while(swapped); 22 } 23 // 第二版bubbleSort,使用newn進行優化 24 template<typename T> 25 void bubbleSort2( T arr[] , int n){ 26 int newn; // 使用newn進行優化 27 do{ 28 newn = 0; 29 for( int i = 1 ; i < n ; i ++ ) 30 if( arr[i-1] > arr[i] ){ 31 swap( arr[i-1] , arr[i] ); 32 // 記錄最後一次的交換位置,在此之後的元素在下一輪掃描中均不考慮 33 newn = i; 34 } 35 n = newn; 36 }while(newn > 0); 37 } 38 int main() { 39 int n = 20000; 40 // 測試1 一般測試 41 cout<<"Test for random array, size = "<<n<<", randome range [0, "<<n<<"]"<<endl; 42 int *arr1 = SortTestHelper::generateRandomArray(n,0,n); 43 int *arr2 = SortTestHelper::copyIntArray(arr1, n); 44 int *arr3 = SortTestHelper::copyIntArray(arr1, n); 45 int *arr4 = SortTestHelper::copyIntArray(arr1, n); 46 47 SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n); 48 SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n); 49 SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n); 50 SortTestHelper::testSort("Bubble Sort 2", bubbleSort, arr4, n); 51 52 delete[] arr1; 53 delete[] arr2; 54 delete[] arr3; 55 delete[] arr4; 56 57 cout<<endl; 58 // 測試2 測試近乎有序的陣列 59 int swapTimes = 100; 60 cout<<"Test for nNearly ordered array, size = "<<n<<", swap time = "<<swapTimes<<endl; 61 arr1 = SortTestHelper::generateNearlyOrderedArray(n, swapTimes); 62 arr2 = SortTestHelper::copyIntArray(arr1, n); 63 arr3 = SortTestHelper::copyIntArray(arr1, n); 64 arr4 = SortTestHelper::copyIntArray(arr1, n); 65 66 SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n); 67 SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n); 68 SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n); 69 SortTestHelper::testSort("Bubble Sort 2", bubbleSort, arr4, n); 70 71 delete[] arr1; 72 delete[] arr2; 73 delete[] arr3; 74 delete[] arr4; 75 76 cout<<endl; 77 // 測試3 測試完全有序的陣列 78 // 對於完全有序的陣列,氣泡排序法也將成為O(n)級別的演算法 79 swapTimes = 0; 80 n = 10000000; // 由於插入排序法和氣泡排序法在完全有序的情況下都將成為O(n)演算法 81 // 所以我們的測試資料規模變大,為1000,0000 82 cout<<"Test for ordered array, size = " << n << endl; 83 84 arr1 = SortTestHelper::generateNearlyOrderedArray(n, swapTimes); 85 arr2 = SortTestHelper::copyIntArray(arr1, n); 86 arr3 = SortTestHelper::copyIntArray(arr1, n); 87 arr4 = SortTestHelper::copyIntArray(arr1, n); 88 89 // 在這種情況下,不再測試選擇排序演算法 90 //SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n); 91 SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n); 92 SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n); 93 SortTestHelper::testSort("Bubble Sort 2", bubbleSort, arr4, n); 94 95 delete[] arr1; 96 delete[] arr2; 97 delete[] arr3; 98 delete[] arr4; 99 return 0; 100 }
測試結果: