备注:这里使用的插入排序和选择排序都是经过优化后的详细优化请查看上一条博客,编译器使用DEV-C++
冒泡排序算法的运作如下:(从后往前)
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
测试代码:
1 #ifndef OPTIONAL_01_BUBBLE_SORT_SORTTESTHELPER_H 2 #define OPTIONAL_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(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 // 生成一个近乎有序的数组 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 }
测试结果: