冒泡排序的实现及优化和变形
1.概述
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。在一般面试中也是最容易碰到的排序算法。
算法描述
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成。
2.基本实现
参考代码如下
pojo类
public class pojo { public int[] s; public pojo(){} //产生n个随机整数 public pojo(int n){ s=new int ; for(int i=0;i<n;i++) s[i]=new Random().nextInt(n); } //产生n个有序整数,falg为true为顺序,false为逆序 public pojo(int n,boolean falg){ s=new int ; if(falg){ for(int i=0;i<n;i++) s[i]=i; }else{ for(int i=0;i<n;i++) s[i]=n-i; } } //返回前n个数总和 public long average(int n){ long sum=0; for(int i=0;i<n;i++) sum+=s[i]; return sum; } }
maopao类
public class maopao { public static void sort(int[] s){ for(int i=0;i<s.length;i++){ for(int j=0;j<s.length-1-i;j++){ if(s[j]>s[j+1]){ s[j]=s[j]+s[j+1]; s[j+1]=s[j]-s[j+1]; s[j]=s[j]-s[j+1]; } } } } public static void main(String[] args) { pojo a=new pojo(10000); int []s=a.s; System.out.println(Arrays.toString(s)); long startTime=System.nanoTime(); //获取开始时间 sort(s); long endTime=System.nanoTime(); //获取结束时间 System.out.println(Arrays.toString(s)); System.out.println("冒泡排序程序运行时间:"+(endTime-startTime)+"ns"+"\t"+"数组长度为:"+s.length); } }
运行结果
注意代码中"s[j]=s[j]+s[j+1];s[j+1]=s[j]-s[j+1];s[j]=s[j]-s[j+1];",这段代码意思为s[j]与s[j+1]的值交换
3.优化
思考一下,当需要排序的数据是排好的或者接近排好的,这样的话在循环结束前就已经排好了,但是排序还是会循环判断下去,这样会多做不少无用功,那有什么办法让循环停止呢?
我们发现在一次冒泡循环中,如果当前元素与下一个元素不用交换、下一个元素与下下个元素不用交换、下下个元素...那么当前元素一直到最后一个元素一定是排好的,而循环遍历到当前元素时,第一个元素到当前元素已经是排好的了,所有整体就第一个元素到最后一个元素都排好了,可以直接结束了。
参考代码如下
public class maopao1 { public static void sort(int[] s){ for(int i=0;i<s.length;i++){ boolean flag=false; for(int j=0;j<s.length-1-i;j++){ if(s[j]>s[j+1]){ s[j]=s[j]+s[j+1]; s[j+1]=s[j]-s[j+1]; s[j]=s[j]-s[j+1]; flag=true; } } if(!flag) break; } } public static void main(String[] args) { pojo a=new pojo( 3678 10000); int []s=a.s; System.out.println(Arrays.toString(s)); long startTime=System.nanoTime(); //获取开始时间 sort(s); long endTime=System.nanoTime(); //获取结束时间 System.out.println(Arrays.toString(s)); System.out.println("优化冒泡排序程序运行时间:"+(endTime-startTime)+"ns"+"\t"+"数组长度为:"+s.length); } }
运行结果
我在这里增加了一个flag变量来做标记,当满足条件后直接跳出循环。
发现没有,运行时间上基本没什么变化,但是注意我上面说了,当需要排序的数据是排好的或者接近排好的,优化效果就非常明显了。
改变上面maopao1类的代码
这个表示获取从小到大的1-10000排列的数组,我们的目标也是从小打大排序。
结果如下
3.变形
我在这里讲一种新的排序,它叫鸡尾酒排序,或者叫快乐小时排序,当然它不止这两种叫法。他是冒泡排序的一种变形,是基于冒泡排序的。
他的原理是:先找到最小的数字,把他放到第一位,然后找到最大的数字放到最后一位。然后再找到第二小的数字放到第二位,再找到第二大的数字放到倒数第二位。以此类推,直到完成排序。也就是双向的冒泡。
参考代码如下
public class maopao2 { public static void sort(int[] s){ int left=0,right=s.length-1; while(left<right){ //同优化冒泡排序 boolean flag=false; //从右向左冒泡,找最小的 for(int i=right;i>left;i--) if(s[i]<s[i-1]){ s[i]=s[i]+s[i-1]; s[i-1]=s[i]-s[i-1]; s[i]=s[i]-s[i-1]; flag=true; } left++; //从左向右冒泡,找最大的 for(int i=left;i<right;i++) if(s[i]>s[i+1]){ s[i]=s[i]+s[i+1]; s[i+1]=s[i]-s[i+1]; s[i]=s[i]-s[i+1]; flag=true; } right--; if(!flag) break; } } public static void main(String[] args) { pojo a=new pojo(10000); int []s=a.s; System.out.println(Arrays.toString(s)); long startTime=System.nanoTime(); //获取开始时间 sort(s); long endTime=System.nanoTime(); //获取结束时间 System.out.println(Arrays.toString(s)); System.out.println("鸡尾酒排序程序运行时间:"+(endTime-startTime)+"ns"+"\t"+"数组长度为:"+s.length); } }
运行结果
虽然运行时间没有多大改变,但是在某些特定的环境下是要优于冒泡排序的。
改变maopao2类代码:
运行结果:
改变maopao2类代码:
运行结果:
- Java算法实现之冒泡排序及优化
- java版排序算法简介及冒泡排序以及优化,选择排序,直接插入排序,希尔排序,堆排序,快速排序及其优化前言 2 分类 2 稳定性 3 时间复杂度 4 Java实现版本 5 1、冒泡排序 6 2、选择排序
- 冒泡排序优化——Java实现
- 冒泡排序的实现和优化及其与插入,选择排序的比较
- shell脚本实现冒泡排序(优化)
- 使用js实现冒泡排序,并优化。
- 鸡尾酒算法实现冒泡排序的优化
- 冒泡排序的实现及其优化。
- 【LintCode-463】整数排序(Java实现-冒泡排序优化)
- 冒泡排序的实现及其优化。
- 顺序表上实现冒泡排序及其优化
- Java实现冒泡排序以及优化冒泡排序的一些小技巧
- 冒泡排序及其优化的 Java 实现
- 【常用排序算法】冒泡排序与冒泡排序优化改进(Java实现)
- 简单的冒泡排序及其优化(java实现)
- 优化的冒泡排序的实现
- 冒泡排序实现及算法优化(java)
- 冒泡排序实现与性能优化及JDK排序类分享
- 交换排序之冒泡排序(java实现含优化)
- 冒泡排序实现及优化(Java)