从冒泡排序到鸡尾酒排序

大致上,常见的算法就这么多吧!!这个表很有用感谢大佬们总结 

 1、一张很有用的表

2、从冒泡排序开始

直观的感受冒泡排序就是下面这个样子 ,其实简单来说它就是,相邻的两个元素进行比较,然后如果是逆序(这里就按照从小到大进行排序)的话就将两个元素交换,这样一轮过去之后最后的元素就是最大的那个元素。然后进行下一轮,依次进行即可。那么代码实现的话就是个双重for循环!!!

 代码的话大致就是这个样子:

public void sort(int[] array){
        for(int i=0;i<array.length-1;i++){
            for (int j = 0;j<array.length-i-1;j++){
                int temp = 0;
                if(array[j]>array[j+1]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
        }
    }

用一个具体的例子描述一下就是如下图:

                                       

这是经过了一轮的排序,其中最大的元素9排在了最后,可以认为这个元素9是在有序区 ,有序区目前只有一个元素。

 

 3、冒泡排序的优化①

还是上面画的那个例子,依次进行每一轮的排序,其中第六轮如下:

                                                 

第七轮:

                                                   

很明显,经过六轮排序后已经是有序的了,第七轮就是“多此一举”,所以优化的话从这里下手。

考虑一下,如果能做一个标记,标记此时数列是否有序,如果有序的话就不用往下进行了,可以提前结束。所以说可以设置一个boolean值isSorted来标记。

for(int i = 0;i<array.length-1;i++){
            //有序标记,每一轮的初始值位true
            boolean isSorted = true;
          
            for(int j = 0; j < array.length-i-1; j++){
                int temp = 0;
                if(array[j] > array[j+1]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    //有元素交换,所以不是有序的,标记为false
                    isSorted = false;
                }
            }
            if(isSorted)
                break;
    }

 

 4、冒泡排序的优化②

有这样一个数列 

                                            

按照上面冒泡的原理第一轮之后是这样的,它的有序区只有一个元素就是8

                                           

经过第二轮之后,有序区有两个元素7和8

                                              

你可能会注意到一点就是上面所说的有序区的长度跟排序的轮数是相等的,拿这个例子的实际情况来说,正真的有序区大于这个长度。事实上,数列的后半部分4,5,6,7,8都是有序的,如果不考虑这个的话继续进行“冒泡”,后面的元素的相互比较就是浪费。为了避免这种情况,在每一轮的排序后记录下来最后一次元素交换的位置,该位置就是无序数列的边界,它后面的元素就属于有序区是有序的。

                                               

用代码描述的话就是在上面实现的基础上,在设置一个变量lastExchangeIndex  来记录最后一次交换的位置即可

public static void sort(int array[]){
        //设置一个变量记录最后一次交换的位置
        int lastExchangeIndex = 0;
        int sortBorder = array.length-1;
        
        for(int i = 0;i<array.length-1;i++){
            //有序标记,每一轮的的初始值为true
            boolean isSorted = true;
            for(int j=0;j<sortBorder;j++){
                int temp = 0;
                if(array[j] > array[j+1]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    isSorted = false;
                    lastExchangeIndex = j;
                }
            }
            sortBorder = lastExchangeIndex;
            if(isSorted)
                break;
        }
    }

 5、冒泡排序终极优化

先细品一张图,细品。

                                   

用小灰的原话来说“只有元素1的位置不对, 却要进行7轮排序,这也太憋屈了吧!!” 

这么憋屈的原因就是我们使用的冒泡排序法,每次都是从左往右来进行比较,进行单向的位置的交换,所以为了改善这种缺点,有没有一种方法从右往左呢,当然,当纯的 从右往左跟上面的从左往右也就没有区别了,所以考虑一次从左往右再一次从右往左,这样的话就能改善这种方法,这就是鸡尾酒排序方法。

用鸡尾酒排序的话,第一轮跟上面的第一轮一样,从第二轮开始如下:

                                           

第二轮结束之后已经是有序的了,但是流程并没有结束,再从左往右进行第三轮,所有元素位置不变,排序结束。所以说总共用了三轮就将无序数列变成有序的。

/**
 * 鸡尾酒排序
 */
public class CocktailSort {
    public static void sort(int[] array){
        int temp = 0;
        for(int i = 0;i<array.length/2;i++){
            //有序标记,每一轮的初始值位true
            boolean isSorted = true;
            //奇数轮,从左向右比较交换
            for(int j = i; j < array.length-i-1; j++){
                if(array[j] > array[j+1]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    //有元素交换,所以不是有序的,标记为false
                    isSorted = false;
                }
            }
            if(isSorted)
                break;

            //偶数轮开始前,将isSorted标记为true
            isSorted = true;
            //偶数轮,从右往左比较交换
            for (int j = array.length-i-1;j>i; j--){
                if(array[j]<array[j-1]){
                    temp = array[j];
                    array[j] = array[j-1];
                    array[j-1] = temp;
                    //因为有元素交换,所以不是有序的,标记变为false
                    isSorted = false;
                }
            }
            if(isSorted)
                break;
        }

    }

    public static void main(String[] args) {
        int[] array = new int[]{2,3,4,5,6,7,8,1};
        sort(array);
        System.out.println(Arrays.toString(array));
    }

}

 

真心觉得《漫画算法.小灰的算法之旅》这本书挺好的,尤其是对刚入门数据结构的人来说,虽然我不是刚入门,但是我算法很差,我用我能看懂的方式将程序的每一步自己用图形画出来,这样我才能真正的理解这个代码,这个算法,慢慢爬吧,总会有云开日出的时候!!! 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值