冒泡排序算法

来源:互联网 发布:windows 10输入法切换 编辑:程序博客网 时间:2024/06/07 13:31

作者:云都小生


概念



冒泡算法是一种简单的排序算法,时间复杂度为O(N^2)(两层循环)。冒泡算法本质上只有四个字:轻浮重沉

例如对一个数列进行排序 [3,4,12,4,1,6]

轻的气泡就是指最小的数,重的气泡就是指比较大的数,小的数要往前移动,大的数要往后移动。(如果是按照从大到小的顺序,就相反)


简单冒泡排序



我们先来看一张图,这张图是这样的。

这里写图片描述

这里写图片描述

每一层循环我都进行一次对比,将最大的数放到后面去。

public class Bubble {    public static void main(String[] args){        int[] nums = new int[]{123,3,5,1,23,4};        for(int i = 0; i < nums.length-1;i++)   //n个数,外层循环就要进行n-1次        {            for(int j = 0; j < nums.length-1;j++)   //每次循环,都要对整个数列进行一次遍历,找到较大的那个往后排            {                if(nums[j] > nums[j+1]) //一旦前一个比后一个大,就交换位置                {                    int temp;                    temp = nums[j];                    nums[j] = nums[j+1];                    nums[j+1] = temp;                }            }        }        System.out.println(Arrays.toString(nums));    }}

不要光看代码,如果逻辑思维能力不行,可以考虑利用其他方面来理解。例如说,去尝试着调试,跟着每个变量的变化。

还可以借助笔和纸,列出一个数组,记录每次循环i和j都会怎么变化,数组又会进行什么变化。

以前我学的时候也是这样,光看着大脑转不过弯来,我就去调试、用笔和纸去尝试着理解。


冒泡排序优化方案1



如果你上面那个算法搞懂了,恭喜你,完成了第一步,还有第二步。

上面的冒泡算法并不完整,算法一般都是讲究效率,而上一种的代码效率并不高,为什么呢?我们还拿上次的图当案例。

经过第一次循环,我已经将最大的数比较出来,并且放在了最后面——123。

可是我下次循环还会对整个数列进行一轮对比,明明最大数已经比较出来了——就是123,那我就可以不用去对比这最后一个数啦。

同理,经过第二层循环之后,我已经把整个数列中第二大的数放到倒数第二个位置了,下次我就不用跟这个数比较啦。

这里写图片描述

那有什么办法,可以让我节省这一步吗?很简单。

public class Test {    public static void main(String[] args){        int[] nums = new int[]{123,42,33,23,4};        for(int i = 0; i < nums.length-1;i++)        {            for(int j = 0; j < nums.length-i-1;j++)            {                if(nums[j] > nums[j+1])                {                    int temp;                    temp = nums[j];                    nums[j] = nums[j+1];                    nums[j+1] = temp;                }            }        }        System.out.println(Arrays.toString(nums));    }}

在第二层循环的判断条件入手,nums.length-i-1;

第一次,我要比较0~length()-1的数

第二次,我要比较0~length()-2的数

第三次,我要比较0~length()-3的数

···

这样效率就更高了。当需要排序的数越来越多时,前一种方式跟后一种方式就会产生差异。后一种方式才是完整的冒泡排序,精髓就在于第二层的循环判断 j < nums.length-i-1;


冒泡排序优化方案2



这种优化方案,是针对“最好”情况的优化。

什么是最好情况呢。

假设你需要从小到大排序,给你一个数列是这样的 {1,2,3,4,5}

这是不是最好的情况?这个时候我们只需要循环第一次,发现没有一个数需要改变位置的,就证明这是个有序数列,不需要排序了。

public class Test {    public static void main(String[] args){        int[] nums = new int[]{1,2,3,4,5};        boolean if_break = true;                    for(int i = 0; i < nums.length-1;i++)        {            for(int j = 0; j < nums.length-i-1;j++)            {                if(nums[j] > nums[j+1])                {                    int temp;                    temp = nums[j];                    nums[j] = nums[j+1];                    nums[j+1] = temp;                    if_break = false;                }            }            if(if_break)            {                break;            }        }        System.out.println(Arrays.toString(nums));    }}

这个时候,不需要改变任何一个数的位置,所以不会执行if里面的内容。

if_break变量表示的是,这个数列是否是有序数列,有序则是true,无序则是false。

进行第一次循环下来之后,发现这是一个有序数列,就直接跳出循环,不需要再进行之后那些”无用功”了。


总结



冒泡算法是一种比较容易理解的算法,但是效率并不是很高,当数列的长度越来越大,比较的数越来越多时,低效率就会开始凸显。那还有没有其他更有效率的方法呢?跟着我,一起学。

2017/10/14 14:26:46 @Author:云都小生