冒泡排序是一种不断交换相邻的元素的排序,一些元素在不断得被交换中,就像水中冒泡一样,因此得名冒泡排序。
算法原理
1.比较相邻的元素,如果前面元素比后面元素要小,那么则交换这两个元素。
2.对每一组相邻的元素都进行比较,从开始的第一对元素到结尾的最后一对元素依次进行比较,叫做一次冒泡。经过一次冒泡后,能保证最大的元素在最后
3.如果说数组有n个元素,进行1次冒泡后能保证最后1个元素是最大的,也就是说进行1次冒泡能保证排完最后1个元素。那么进行n-1次冒泡后,能保证排完n-1个元素,n-1个元素排序完成,那么整个数组排序完成。因此一共需要冒泡n-1次。
代码
public class Bubble {
//交换a数组中索引x和索引y处的元素
private static void exch(Comparable[]a,int x,int y){
Comparable temp=a[x];
a[x]=a[y];
a[y]=temp;
}
//判断a元素是否小于b元素
private static boolean less(Comparable a,Comparable b){
return a.compareTo(b)<0;
}
public static void sort(Comparable[]a){
final int N=a.length;
//进行n-1次冒泡
for(int i=N-1;i>0;i--){
for(int j=0;j<i;j++){
if(less(a[j+1],a[j]))exch(a,j,j+1);
}
}
}
public static void main(String[] args) {
Integer[]a=new Integer[50];
for (int i = 0; i < a.length; i++) {
a[i]=(int)(Math.random()*50);
}
System.out.println("排序前");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
System.out.println();
System.out.println("排序后");
sort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
}
}
复杂度分析
- 时间复杂度:共进行n-1次冒泡,第一次比较n-1次,第二次比较n-2次,第n-1次比较1次。1+2+3…+n-1=n(n-1)/2,因此时间复杂度为O(n^2)
- 空间复杂度:只用到一个temp变量,空间复杂度为O(1)
冒泡排序的优化
mark:今天是2022年1月12日,在一次面试中突然被问到了冒泡排序该如何优化!打开这篇帖子看一下,我学java已经快两年了,不知不觉变秃了却没变强,继续努力!
第一种优化思路
假如在第一次冒泡后数组已经完全有序,按照冒泡排序的算法还会继续冒泡,此时其实没有必要。可以用一个boolean类型的变量标记此次排序中是否有交换元素,初始为false。当有交换元素后把变量标记为true,如果经过一轮冒泡后,变量还是false,name说明当前数组已经有序了。直接break跳出循环结束。
(PS:面试里我说的每轮冒泡后在检查一次看看是不是有序的,面试官不太满意。其实在冒泡的时候就已经比较了一轮了,完全可以像上面那样写。)
public void bubbleSort(int[]nums){
if(nums==null|| nums.length<2)return ;
int n=nums.length;
for (int i = n-1; i >=0 ; i--) {
for (int j = 0; j <i; j++) {
boolean exch=false;
if(nums[j]>nums[j+1]){
exch=true;
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
//这一趟冒泡没有交换元素,说明数组已经有序
if(!exch)break;
}
}
}
第二种优化思路
针对向[5,4,3,2,1,6,7,8,9,10]这种后半段有序而前半段无序的数组,冒泡的交换主要在前面,我们可以标记下每次冒泡中最后交换元素的索引位置,那么在这个索引位置后面的元素都已经全部有序,便不用继续排序
public void bubbleSort(int[]nums){
if(nums==null|| nums.length<2)return ;
int n=nums.length;
int k=n-1;
for (int i = n-1; i >=0 ; i--) {
for (int j = 0; j <Math.min(k,i); j++) {
boolean exch=false;
if(nums[j]>nums[j+1]){
exch=true;
k=j;
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
//这一趟冒泡没有交换元素,说明数组已经有序
if(!exch)break;
}
}
}
第三种优化思路:鸡尾酒排序
吃完饭在更!