冒泡排序优化 (JAVA)
排序是算法的基础部分, 冒泡是排序的基础方法,
先介绍普通的冒泡排序, 要看优化的直接跳过好了:
(这里统一指的从小到大排序)
先说什么叫冒泡, 基本思路就是
遍历一次数组,把最大的挑出来放在最后 (此时最后一位已经完成,后续不再比较),
第二次遍历把第二大的放在倒数第二位 (此时最后两位已经完成,不再比较)
.........有N个数就遍历N遍后所有数就完成了,也就通过冒泡法完成了排序
图片来源于百度图片,有点幼稚...但是清晰明了
每一遍的遍历挑出最大的数是通过从第一位开始与后者两两比较实现的,
如果前者小于后者说明小的在前,不用动,
如果前者大于后者说明这两个数相对位置放反了 ,需要交换这两个数的位置
这样比较完一趟,我们叫完成了一次遍历,这次遍历能保证最大的数放在了最后的位置(这里初学者可能会不明白, 自己画一画)
这样完成N次遍历也就完成了整个数组的排序,这种方法就叫冒泡法排序,
因为每次排序都是把其中一个数挑出来慢慢向后移,这个过程有些像气泡慢慢浮上水面的样子,因为称之为冒泡法排序
贴一个自己的java实现冒泡排序
package aa;
public class ss {
public static void main(String[] args) {
//随便定义的数组
int arr[]= {3,8,5,10,1,99,8,1,5,4,2,5,19,4,2,8,21,46,8,5,2,1,15};
for(int i=0;i<arr.length;i++) //这控制遍历的次数,arr.length次
{
for(int j=0 ; j< arr.length-1;j++)
{ //这的if判断前者是否比后者大,如果是:交换
if(arr[j]>arr[j+1])
{
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for(int b : arr) //循环输出arr数组
System.out.println(b);
}
}
这样可以完成简单的排序,时间复杂度是O(n2)
那哪里可以优化呢?
第一次遍历完成后最大的元素放在了正确的位置, 后边的遍历就没必要和最后一位比较大小了,
第一次遍历完成后最大的两个元素都不用去比较了,
但是我们的程序每次遍历 比较的位数都是N位,即使后几位已经没必要比较了,
所以这里就是要优化的地方,
每次遍历完成后下次都减少一位比较的位数,
思考一下我们的JAVA程序,外层循环是控制 遍历次数, 由i变量计数
内层循环控制每次遍历的两两比较次数, 次数是 arr.length-1 (之所以-1是因为最后一位不能和后一位比较了, 会造成下标越界)
按照我们的分析 就是比较的次数减去已经完成的遍历次数就搞定了,
也就是说把比较次数arr.length-1改成arr.length-1-i 就可以啦!
我们贴上改了之后的程序(只是这一个语句变了):
package aa;
public class ss {
public static void main(String[] args) {
int arr[]= {3,8,5,10,1,99,8,1,5,4,2,5,19,4,2,8,21,46,8,5,2,1,15};
for(int i=0;i<arr.length;i++)
{
for(int j=0 ; j< arr.length-i-1;j++)
{
if(arr[j]>arr[j+1])
{
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for(int b : arr)
System.out.println(b);
}
}
当然,在数组比较小的时候是体会不出优化后的效果的,当数据量贼大的时候差距就很大啦,
那么这里还有一个问题, 假如数组是这样的:
9,1,2,3,4,5,6,7,8
当完成第一遍遍历的时候就完成了数组的排序,但是程序还会接着往下跑,浪费了不必要的时间,
所以这里还可以做一些修改, 每次遍历加一次判断条件,
如果一次遍历没有发现需要交换的地方就说明完成了排序,
break停止循环即可