冒泡排序法

冒泡排序并不是课程中的内容,但liuyubo老师将他的代码写在了github中,顺便学习了一下,但是对于他的优化方法的测试结果,我还有些不太理解。

思路

冒泡排序依然是一个O(n²)的排序,思路是:

通过不断将自己与自己后一个元素比较并交换,将较大的元素交换到后面,这样过完一整趟,就可以让最大的元素归位到最后,此时我们可以保证至少数组中最后一个元素是排好序的,以此类推,下一趟排序我们将扫描的范围缩小1,重复这个过程,直到过完一整趟都没有发生交换,证明数组已经排好序。

实现

先贴代码

void bubbleSort(int arr[], int n){
    bool isSwap;
    do{
        isSwap = false;
        for (int i = 0; i<n-1; i ++) {
            if (arr[i] > arr[i + 1]){
                swap(arr[i], arr[i + 1]);
                isSwap = true;
            };
        }
        n --;
    }while(isSwap);
}

意思应该已经比较清楚了,这个版本的冒泡排序和插入排序一样是可以提前结束的,这意味着它在近乎有序的数组排序中将是一个O(n)级别的算法。

优化

在上述的分析中,我们是通过每一趟将扫描范围缩小1来优化整个排序的,但我们还可以将缩小范围的步伐迈得更大一些,事实上我们可以保证每次扫描的最后一次交换都确定了,最后交换的那个元素后面直至数组末尾的部分是有序的,因此我们可以做如下改动

void bubbleSort2(int arr[], int n){
    int end;
    do{
        end = 0;
        for (int i = 0; i<n-1; i ++) {
            if (arr[i] > arr[i + 1]){
                swap(arr[i], arr[i + 1]);
                end = i + 1;
            };
        }
        n = end;
    }while(n > 0);
}

这里用end来记录每趟扫描最后交换的位置,然后将范围的右边界缩小到这个位置,理论上可以使性能得到优化。

测试

这个部分就很诡异了,我们先来看看吧。

随机数组排序

insertion sort2 : 0.085354s
bubble sort : 0.311727s
bubble sort2 : 0.311345s

可以看到随机的情况下对10000个数排序,冒泡排序的水平在O(n²)的正常范围内,然而优化后的冒泡排序并没有体现出什么优势。

近乎有序的数组

insertion sort2 : 0.000269s
bubble sort : 0.114654s
bubble sort2 : 0.088130s

在近乎有序的情况下,优化后的冒泡排序有了一些优势,但依然比插入排序要慢很多。

完全有序的数组

insertion sort2 : 0.000042s
bubble sort : 0.000026s
bubble sort2 : 0.000025s

完全有序的情况下,冒泡排序整体快于插入排序,但优化效果并不是很明显。

结论

没有结论。。。很奇怪,这么看来优化似乎没有起到很明显的作用,后续再研究一下。


种一棵树最好的时间是在十年前,而后是现在。

Loading Disqus comments...
Table of Contents