冒泡排序的优化你真的不知道?面试踩坑优化
Posted 大数据修行直通车
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冒泡排序的优化你真的不知道?面试踩坑优化相关的知识,希望对你有一定的参考价值。
排序算法之冒泡排序
一定看到最后,算法最重要的就是不断优化,思路最重要
【课代表总结】最简单的冒泡也有很多门道!!!面试过程中,多和面试官沟通自己的思路,不断优化,探讨,比干巴巴的写写写更容易offer到手
1、基本思路(从小到大排序)
通过对待排序序列从前往后依次比较,若发现逆序(前一个数字大于后一个数字)则交换位置,使值较大的元素逐渐从前移动到后部。
设待排序列为arr[5]={10,1,3,2,9},设置一个临时变量temp,用来帮助两个值的交换。第一趟排序首先比较arr[0]和arr[1],发现arr[0]>arr[1],则两个数值交换位置 然后再比较arr[1]和arr[2],依次类推。
(1)第一趟排序代码为:
int first=0,last=0,temp=0;
for(int i=0;i<arr.length-1;i++){
if(arr[i]>arr[i+1]){
temp=arr[first];
arr[first]=arr[last];
arr[last]=temp;
}
}
第一趟排序之后的结果是:arr[5]={1,3,2,9,10};即将数组中最大的数移动到数组的尾部。在第二趟排序中只需要比较前四个数值就可以了,即前arr.length-1个数值。
(2)在第二趟排序中找到第二大的数值,并放在数组中倒数第二个位置,因此第三趟排序只需要比较前arr.length-2个数就可以了。依次类推,当完成arr.length-1次排序之后,就可以保证整个数组是有序的。代码表示如下:
public static void bobbsort(int[] arr){
int temp=0;
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
2、优化
通过上一个例子arr[5]={10,1,3,2,9}可以看出,在第一趟排序后得到的结果为 arr[5]={1,3,2,9,10};第二趟的排序结果为arr[5]={1,2,3,9,10},此时数组已经有序,后面的第三趟第四趟排序完全是浪费时间。
因此我们可以通过设置一个flag来判断每趟排序是否有交换;若没有交换,则说明数组已经有序,可以退出循环。具体代码为:
public static void bobbsort(int[] arr){
int temp=0;
boolean flag=false;
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
flag=true;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
if(!flag){ //如果flag的值依旧为false 则说明没有交换
break;
}else{ //否则flag的值为true,说明交换 此时 要将flag的值重新置为false
//进行下一次的判断
flag=false;
}
}
System.out.println(Arrays.toString(arr));
}
3、二次优化
在冒泡排序的过程中,经常会遇到这样的一种情况:在第i趟排序过程中,第i大的数据已经在相应的位置了,甚至第i-1大的数据也已经在相应的位置上了,这样我们在进行第i趟排序时会出现多余的比较。
比如数组arr[5]={10,4,3,8,9},第一趟排序后结果为arr[5]={4,3,8,9,10},此时,元素8,9已经在相应的位置上了,但是在第二趟排序中依旧会做比较。
因此,为了避免多余的比较,设置一个变量标记每趟排序后最后的交换位置,在进行下一趟排序时,只要比较最后交换位置之前的元素即可。代码如下:
public static void bobbsort(int[] arr){
int temp=0;
boolean flag=false;
int lacat=0; //标记最后交换的位置
int len=arr.length-1;
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<len;j++){
if(arr[j]>arr[j+1]){
flag=true;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
lacat=j;
}
}
len=lacat;
if(!flag){ //如果flag的值依旧为false 则说明没有交换
break;
}else{ //否则flag的值为true,说明交换 此时 要将flag的值重新置为false
//进行下一次的判断
flag=false;
}
}
System.out.println(Arrays.toString(arr));
}
4、优化前后性能比较
冒泡排序算法在优化前最好和最坏情况下时间复杂度都为O(n^2), 而在第一次优化和第二次优化之后最坏的情况下依旧为O(n^2),但是最好的情况下时间复杂度变为O(n)。
相比较第一次优化和第二次优化在程序中设置80000个随机整数数组,分别记录时间,代码如下:
public static void main(String[] args) {
int[] arr=new int[80000];
for(int i=0;i<80000;i++) {
arr[i]=(int)(Math.random()*800000);
}
System.out.println("排序前时间为");
Date date1=new Date();
SimpleDateFormat simpaleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str=simpaleDateFormat.format(date1);
System.out.println(date1Str);
bobbsort2(arr);
Date date2=new Date();
String date2Str=simpaleDateFormat.format(date2);
System.out.println("排序完成的时间为:"+date2Str);
}
5、实战对比执行时间
(3)两次优化后运行时间
6、总结
上面算法的优化思路,绝对可以让你与众不同。
无论简单的算法还是更为复杂的,主要是解决问题的思路,举一反三,多思考,很多地方都可以应用的到!
PS: 笔者刚建了个学习交流群,禁广告、推广,大家有啥问题也可以在群里提问,有需要的小伙伴可以加一下~
加群方式 - 扫描下方 以上是关于冒泡排序的优化你真的不知道?面试踩坑优化的主要内容,如果未能解决你的问题,请参考以下文章