冒泡算法作为常见的八大排序算法,是有必要掌握的。
冒泡排序算法是稳定排序,复杂度为O(n^2)。
github地址:https://github.com/huangxinchao/algorithm(欢迎相互交流)
version 1
/*
* 冒泡排序 version 1
* example: 3,2,1,4,5,6
* 第零次:2 1 3 4 5 6 //确定最大数6
* 第一次:1 2 3 4 5 6 //确定 5,6
* 第二次:1 2 3 4 5 6 //确定 4,5,6
* 第三次:1 2 3 4 5 6 //确定3,4,5,6
* 第四次:1 2 3 4 5 6 //确定2,3,4,5,6
* 第五次 1 2 3 4 5 6 //确定1,2,3,4,5,6
*
* 特点:
* 1,循环一行确定一个有序的数的位置,需要循环的次数n,n为数组长度。
* 2,每行中两个数比较的次数为5-n(n为次数,n从零开始)
*
* 备注:我们将第零次,第一次这种每次循环确定一个数的位置称之为行循环,每一行中两个元素的比较次数称之为列循环
* */
public static int bubble(int[] arr,int n){ //arr为数组,n为数组长度
if(arr.length<1)return -1 ;
System.out.println("sort before:");
for(int num:arr){
System.out.print(num+",");
}
int executeNum = 0 ;
for( int i = 0 ; i < n - 1 ; ++i){
for( int j = 0 ; j < n - 1 - i ; ++j ){
executeNum++ ;
if(arr[j]>arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp ;
}
}
}
System.out.println();
System.out.println("sort after:");
for(int num:arr){
System.out.print(num+",");
}
System.out.println();
System.out.println("version 1 executeNum:"+executeNum);
return 1 ;
}
version 2
/*
* 冒泡排序 version2
* example: 3,2,1,4,5,6
* 第零次:2 1 3 4 5 6 //确定最大数6
* 第一次:1 2 3 4 5 6 //确定 5,6
* 第二次:1 2 3 4 5 6 //确定 4,5,6
* 第三次:1 2 3 4 5 6 //确定3,4,5,6
* 第四次:1 2 3 4 5 6 //确定2,3,4,5,6
* 第五次 1 2 3 4 5 6 //确定1,2,3,4,5,6
*
* 第零次排序后其实就已经确定所有元素的位置。即当一轮循环结束后,没有发生元素交换,就能确定已经排好序了。
*
* */
public static int bubble2(int[] arr,int n){ //arr为数组,n为数组长度
if(arr.length<1)return -1 ;
System.out.println("sort before:");
for(int num:arr){
System.out.print(num+",");
}
int executeNum = 0 ;
for( int i = 0 ; i < n - 1 ; ++i){
boolean isSort = true ;
for( int j = 0 ; j < n - 1 - i ; ++j ){
executeNum++ ;
if(arr[j]>arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp ;
isSort =false ;
}
}
if (isSort)break;
}
System.out.println();
System.out.println("sort after:");
for(int num:arr){
System.out.print(num+",");
}
System.out.println("version 2 executeNum,"+executeNum);
return 1 ;
}
version 3
/**
* 冒泡排序 version 3
* * example: 3,2,1,4,5,6
* * 第零次:2 1 3 4 5 6 //确定最大数6
* * 第一次:1 2 3 4 5 6 //确定 5,6
* * 第二次:1 2 3 4 5 6 //确定 4,5,6
* * 第三次:1 2 3 4 5 6 //确定3,4,5,6
* * 第四次:1 2 3 4 5 6 //确定2,3,4,5,6
* * 第五次 1 2 3 4 5 6 //确定1,2,3,4,5,6
*
* 1,在version2的基础上,只要第零次排序即可。但是第零次的元素比较次数是5次,观察发现,其实
* 只要比较2,1,3前面三个,因为后面已经排好序。
* 2,回看第一个版本的想法,每一次循环默认确定一个数的位置。但是以上的例子一次循环中可能会确定多个数的位置。
* 即确定有序区范围扩大,不仅仅是每次增加一个。将每次交换的位置确定为有序区和无序区的分界 。
*/
public static int bubble3(int[] arr,int n){ //arr为数组,n为数组长度
if(arr.length<1)return -1 ;
System.out.println("sort before:");
for(int num:arr){
System.out.print(num+",");
}
int executeNum = 0 ;
int eachChangePostion = arr.length-1 ;
int lastChangePosition = arr.length-1 ;
for( int i = 0 ; i < n - 1 ; ++i){
boolean isSort = true ;
for( int j = 0 ; j < lastChangePosition ; ++j ){
executeNum++ ;
if(arr[j]>arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp ;
isSort =false ;
eachChangePostion = j+1 ; // 记录每次行循环中列循环的交换位置。
}
}
lastChangePosition = eachChangePostion ;//将列循环中的最后一个交换位置确定为有序区和无序区的分界
System.out.println();
System.out.println("lastChangePosition:"+lastChangePosition);
for(int k =0;k<arr.length;k++){
System.out.print(arr[k]+",") ;
}
if (isSort)break;
}
System.out.println("sort after:");
for(int num:arr){
System.out.print(num+",");
}
System.out.println();
System.out.println("version 3 executeNum,"+executeNum);
return 1 ;
}
public static void main(String[] args){
int[] arr = {3,2,1,4,5,6};
bubble(arr,arr.length);
int[] arr2 = {3,2,1,4,5,6};
bubble2(arr2,arr2.length);
int[] arr3 = {3,2,1,4,5,6};
bubble3(arr3,arr3.length) ;
}