一 冒泡算法及其优化延伸

1.1 冒泡算法概述

      冒泡算法的英文名师Bubble Sort,是一种最基础的交换排序。

       在我们平时喝的汽水的时候,会有很多小气泡飘上来。这是因为小气泡里面的二氧化碳要比水轻,所以会往上浮。

       而之所以把冒泡排序叫冒泡排序,正是因为这种算法的每一个元素像小气泡一样,根据自身大小,一点一点向数组的一侧移动。

       移动规则:把数组中相邻的两个元素两两比较,根据大小来交换元素的位置

1.2 冒泡算法的优化

1.2.1 初版冒泡算法

根据冒泡算法的思想,很容易写出:

    public static void bubbleSort(int[] array){

        for (int i = 0; i < array.length-1; i++) {

            for (int j = 0; j < array.length -1; j++) {

                if( array[j] > array[j+1] ){

                   int temp  = array[j];

                   array[j] = array[j+1];

                   array[j+1] = temp;

                }

            }

        }

    }

就是一个简单的双循环,这样写基本满足了要求,但是效率确特别低,因为每次循环都对数组进行一次遍历,共比较了(n-1)^2次。当数组元素个数较多的时候,运算速度是非常慢的。

而且,很容易发现一个问题:当数组在第i(i<n)次已经是有序数列的时候,程序会继续往下执行。所以,我们对这种算法进行了优化。

1.2.2 二版冒泡算法

       上面的问题也就是说:当某次循环遍历数组时,没有发生元素之间的交换,说明数列已经排序完成。根据这种思路,将程序优化如下:

    public static void bubbleSort(int[] array){

        for (int i = 0; i < array.length-1; i++) {

      boolean isSorted = true;

            for (int j = 0; j < array.length-1; j++) {

                if( array[j] > array[j+1] ){

                   int temp  = array[j];

                   array[j] = array[j+1];

                   array[j+1] = temp;

                   isSorted = false;

                }

            }

            if(!isSorted) break;

        }

    }

       利用一个布尔变量isSorted作为标记。如果在本轮循环中,有元素的交换,就把改变该变量的值,在每轮循环后进行判断:如果没有元素之间的交换,就直接跳出循环,反之继续执行循环。

       这看似已经达到了最优,但是细细观察的时候便会发现:如果数组的第j(j<n)个元素之后的数字队列在第i(i<n)次循环已成有序数列,在之后的循环中,依然会对已经有序的数列部分进行遍历。因此,我们还有需要优化的地方。

1.2.3 三版冒泡算法

       根据上面提到的不足之处,不难想到:只需要对每轮循环中,最后一次交换元素顺序的地方进行标记,在下一次循环中,只需要遍历到标记的数组位置即可。对代码进行第二次优化:

    public static void bubbleSort(int[] array){

        int endindex = array.length-1, lastchangeindex = 0;

        for (int i = 0; i < array.length-1; i++) {

            boolean isSorted = true;

            for (int j = 0; j < endindex; j++) {

                if( array[j] > array[j+1] ){

                   int temp  = array[j];

                   array[j] = array[j+1];

                   array[j+1] = temp;

                   isSorted = false;

                   lastchangeindex = j;

                }

            }

            if(!isSorted) break;

            endindex = lastchangeindex;

        }

    }

       到了这步,依然不是最优的,还有一种算法叫鸡尾酒算法,是基于冒泡算法一种升级算法。

1.3 鸡尾酒算法

       鸡尾酒排序又叫定向冒泡排序、鸡尾酒搅拌排序、涟漪排序、来回排序等。与冒泡算法的单向排序不同,鸡尾酒算法是双向在序列中排序:每轮循环,先找到最大的数字放在最后一位,再找出最小的放在第一位,以此类推

       根据之前的优化思路,优化后的鸡尾酒算法的代码如下:

    public static void cocktailSort(int[] array){

        int endindex = array.length-1, startindex = 0, lastchangeindex = 0, firstchangeindex = 0;

        for (int i = 0; i < array.length-1; i++) {

            boolean isSorted = true;

            for (int j = startindex; j < endindex; j++) {

                if( array[j] > array[j+1] ){

                   int temp  = array[j];

                   array[j] = array[j+1];

                   array[j+1] = temp;

                   isSorted = false;

                   lastchangeindex = j;

                }

            }

            for(int m = endindex; m > startindex; m--){

                if(array[m] < array[m-1]){

                   int temp = array[m];

                   array[m] = array[m-1];

                   array[m-1] = temp;

                   firstchangeindex = m+1;

                }

            }

            if(isSorted) break;

            startindex = firstchangeindex;

            endindex = lastchangeindex;

        }

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值