冒泡排序算法
来源:互联网 发布: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:云都小生
- 排序算法--冒泡排序
- 排序算法-冒泡排序
- 排序算法--冒泡排序
- 排序算法--冒泡排序
- 排序算法-冒泡排序
- 排序算法 冒泡排序
- 排序算法-- 冒泡排序
- 排序算法-冒泡排序
- 排序算法---冒泡排序
- 排序算法-冒泡排序
- 排序算法--冒泡排序
- 排序算法--冒泡排序
- 排序算法--冒泡排序
- 排序算法--冒泡排序
- 排序算法--冒泡排序
- 排序算法--冒泡排序
- 排序算法 冒泡排序
- 排序算法-冒泡排序
- CentOS下Nginx的HTTPS配置
- data.field.属性赋值
- 中企动力牵手七鑫易维 以眼球追踪技术剔除建站顽疾
- Struts2-day02 获取Servlet API OGNL表达式 ValueStack ActionContext ValueStack存数据 取数据 Interceptor
- 树莓派入门
- 冒泡排序算法
- APUE(第三版)源码配置
- debian 9 fancontrol
- android KeyEvent中各种值
- 图像语义分割概述
- 正则表达式常用类
- 亚马逊AWS EC2 ping不通的原因
- TCP/IP协议图
- 1027 大数乘法 ——51Nod