冒泡排序与选择排序的优化
冒泡排序跟选择排序是八大排序里最简单的两个,有时候简单意味着高效,但这种想法在这两种排序上行不通,恰恰这两种排序的时间复杂度都是O(n^2)级别的,相对于快排的平均时间复杂度O(nlog2n)来说,确实慢了不少。因此,在还不会使用别的排序方法之前,我们可以先对这两种排序方法进行优化,尽量减少运行时间。
一、冒泡排序
冒泡排序有两种比较好的优化方法:
1.在二级循环外进行优化:
这种方法即在两个for循环之间加入一个标志变量flag,先贴代码:(这是升序排序)
1 void BubbleSort_Optimization_1(int arr[],int size) { 2 for (int i = 0;i < size-1;i++) { 3 int flag = 1; 4 for (int j = 0;j < size - 1 - i;j++) { 5 int temp; 6 if (arr[j] > arr[j + 1]) { 7 temp = arr[j + 1]; 8 arr[j + 1] = arr[j]; 9 arr[j] = temp; 10 flag = 0; 11 } 12 } 13 if (flag) 14 break; 15 } 16 return; 17 }
代码第三行处定义了一个标志变量flag,赋初值为1,进入二级循环,只要在二级循环里不会进入if()语句,那么flag的值就会为1,如果执行完二级循环后flag的值仍为1就意味着整个数列从下标0开始到size-1-i为止都是有序的,那么接下来的外层循环就没必要再进行了,直接结束排序过程。
2.第二种优化即是对内层循环进行的优化:
1 void BubbleSort_Optimization_2(int arr[], int size) { 2 int k = size - 1; 3 int temp_k; //temp_k用来暂时存k应赋予的值 4 for (int i = 0;i < size;i++) { 5 int flag = 1; 6 for (int j = 0;j < k;j++) { //这里的循环的上界设置为k 7 int temp; 8 if (arr[j] > arr[j + 1]) { 9 temp = arr[j + 1]; 10 arr[j + 1] = arr[j]; 11 arr[j] = temp; 12 temp_k = j; //这里将最后一次交换值时的下标j记录下来,等待赋予k 13 flag = 0; 14 } 15 } 16 k = temp_k; 17 if (flag) //这里依旧是只要数列后边有序就结束排序 18 break; 19 } 20 return; 21 }
其实上面的代码时两种优化的结合体,第二种优化的关键点在内层循环的上界设置为k,而k的值来自最后一次交换变量所对应的下标j,这样就可以更进一步把排序的范围缩小,减少时间。
二、选择排序的优化
本博文只列出一种选择排序的优化方法:
一般的选择排序每遍历一次数组,只找出最大或最小的那个值,那如果我们在一次遍历之后就把最大和最小值都找出来呢,时间在理论上会比原来少花一半左右。具体代码如下:
1 void SelectionSort_Optimization(int arr[], int size) { 2 int left=0, right=size-1; //left跟right用于循环上下界的左右逼近 3 4 while(left<right){ 5 int temp; 6 int max=right, min=left; 7 for (int i = left;i <= right;i++) { 8 if (arr[i] > arr[max]) { 9 max = i; 10 } 11 if (arr[i] < arr[min]) { 12 min = i; 13 } 14 } 15 16 temp = arr[max]; // 17 arr[max] = arr[right]; // 这块代码将遍历后的最大值交换到右边 18 arr[right] = temp; // 19 20 if (min == right) { // 这段代码存在的意义在于可能存在min==right 21 min = max; // 的情况,在上面的arr[right]与arr[max]的 22 } // 值交换后,arr[left]就应该与arr[max]交换 23 24 temp = arr[min]; // 25 arr[min] = arr[left]; // 交换最小值到左边 26 arr[left] = temp; // 27 28 left++; 29 right--; 30 } 31 return; 32 }
上面的优化相比于原来的选择排序来说在实现上复杂了一点,但在效率上却好了不少。
本文并非原创,只是对自己学习的一个总结,主要参考来自以下两篇博文:
http://blog.csdn.net/yanxiaolx/article/details/51622286
http://blog.csdn.net/qq_26768741/article/details/53313093