关于冒泡排序的优化

  关于冒泡排序的基本思想前面已有介绍,那么我现在考虑这样一个问题冒泡排序还能不能进行优化?

假设我们有这样一个数列:
8 2 3 9 10 11
我们需要一个升序的数列那么排序的过程是这样的:
2 3 8 9 10 11
2 3 8 9 10 11
2 3 8 9 10 11
2 3 8 9 10 11
2 3 8 9 10 11
2 3 8 9 10 11

我们可以看到在第一次就已经排完了,然而排序还在进行,这就很难受了
那么我们是不可以这样做一个标记记录一次遍历后他是否还进行交换,如果遍历完一遍
还没有进行过一次交换,那就意味着这个序列已经是有序的了。不过这个我在前面的代
码里已经写出来了就不多说了。

我们在举一个例子:5 6 3 8 1 9 10 11 20

5 3 6 1 8 9 10 11 20 
3 5 1 6 8 9 10 11 20 
3 1 5 6 8 9 10 11 20 
1 3 5 6 8 9 10 11 20 
1 3 5 6 8 9 10 11 20 
可以看出来如果以n-i设为界限,一躺遍历后后面5个已经是有序的了,然而还是每次都遍历上一次 我们可以以一
个变量记录最后一次交换的下标,这个下标后面已经是有序的了。这样就可以在第二次遍历时在6就结束了。
代码如下:

    int tmp  = 0,border=n,lastExchange=0;
    bool isSorted;
    for(int i = 0; i < n; i++)
    {
        isSorted = true;           //有序标记,每一轮的初始是true
        for(int j = 0; j < border; j++)
        {
            if(array[j] > array[j+1])
            {
                tmp = array[j];
                array[j] = array[j+1];
                array[j+1] = tmp;      //有元素交换,所以不是有序,标记变为false
                isSorted = false;
                lastExchange= j;       //把无序数列的边界更新为最后一次交换元素的位置
            }
        }
        if(isSorted)break;
        border=lastExchange;
    }



这一次的代码中,border就是无序数列的边界。每一轮排序过程中,border之后的元素就完全不需要比较了,肯定是有序的。

那我们下面再举一个例子:2 3 4 5 6 7 8 1

2 3 4 5 6 7 1 8
2 3 4 5 6 1 7 8
2 3 4 5 1 6 7 8
。。。
1 2 3 4 5 6 7 8
我们可以看到 明明2到8都已经有序了只有1位置不对。却还是进行了7次排序。很郁闷啊,但是如果进行一次但是如果我们换一下遍历的方向呢:
第一轮:还是从左往右遍历   2 3 4 5 6 7 1 8 最后还是1和8换
第二轮:反过来从右往左遍历 1 2 3 4 5 6 7 8 就是1和7换 1和6换 1和5换。。。1和2换
第三轮:还是从左往右遍历   1 2 3 4 5 6 7 8 没有发生交换 结束排序
代码如下:


    int tmp  = 0,borderr=n,lastExchange=0,borderl=0;
    //没有发生交换的话直接就break了 所以一个lastExchange够用了 太多我感觉乱的晃。。。
    bool isSorted;
    for(int i = 0; i < n; i++)
    {
        //单数轮 1 3 5等
        isSorted = true;           //有序标记,每一轮的初始是true
        for(int j = borderl; j < borderr; j++)
        {
            if(array[j] > array[j+1])
            {
                tmp = array[j];
                array[j] = array[j+1];
                array[j+1] = tmp;      //有元素交换,所以不是有序,标记变为false
                isSorted = false;
                lastExchange= j;       //把无序数列的边界更新为最后一次交换元素的位置
            }
        }
        if(isSorted) break;
        borderr=lastExchange;

        //开始偶数轮 2 4 6轮
        isSorted = true;          
        for(int j = borderr; j > borderl; j--)
        {
            if(array[j-1] > array[j])
            {
                tmp = array[j];
                array[j] = array[j+1];
                array[j+1] = tmp;      
                isSorted = false;
                lastExchange= j;                   
            }
        }
        if(isSorted) break;
        borderl=lastExchange;
    }

没用编译器不保证运行结果,但是思路是对的 -.-|| 。这个升级版的冒泡排序又叫鸡尾酒排序或者快乐小时排序(我也不知道为啥)。

猜你喜欢

转载自blog.csdn.net/qq_36323837/article/details/86675357
今日推荐