前言基础:
1、冒泡排序法的时间复杂度为O(n2),空间复杂度为O(1),不需要额外的辅助空间。是一种稳定的排序算法。
2、冒泡实质是不断两两比较,一旦两个相邻的元素是逆序的,就会交换这两个元素的位置,
最终进行n-1次这样的操作。
3、每轮循环结束之后过后,保证了arr[n-i,n]是有序的,并且保证了倒数第i个元素呆在了该元素应该呆在的位置。下论循环后面这i个元素不再进入比较交换。
4、每次排序之后,就会将整个数组的杂乱度减小,即减小逆序对的个数。
5、外层循环i的含义:i不仅表示了循环的总轮数,而且i还表示已经排好序的元素个数。
排序过程
第一版本冒泡排序(最流行版本):
public static<E extends Comparable<E>> void Sort(E arr[]){
//循环n-1次
for (int i = 0; i < arr.length-1; i++) {
Boolean flag=false; //当进行一次没有位置交换说明数组是有序的
//后i个元素已经排好序,所以每次对[0,arr.length-i-1]进行排序
for (int j=0;j<arr.length-i-1;j++){
if (arr[j].compareTo(arr[j+1])>0){
Util.swap(arr,j,j+1);
flag=true;
}
}
if (!flag) break;
}
}
第二版冒泡排序(最终优化版本):
在第一版中我们发现如果对于321456这样的数组在第一次循环结束之后456就已经呆在了其应该呆在的位置,之后的循环就没有必要再在对这些元素进行遍历,于是根据i可以表示已经排好的元素个数这一性质进行了如下优化:
public static<E extends Comparable<E>> void bestSort(E arr[]){
//i不仅可以表示循环的次数,还可以表示已经排好序的元素个数
//因为每次循环结束之后arr[n-i,n)是有序的
for (int i = 0; i < arr.length-1; ) {
Integer lastSwapIndex=0;
for (int j=0;j<arr.length-i-1;j++){
if (arr[j].compareTo(arr[j+1])>0){
Util.swap(arr,j,j+1);
lastSwapIndex=j+1;
}
}
//下面的if语句可以直接省略,因为当没有进行交换的
// 时候,lastSwapIndex=arr.length,for循环就会停止了
// if (lastSwapIndex==0) break;
i=arr.length-lastSwapIndex;
}
}
冒泡排序逆向版本(将之前的逆过来):
之前的冒泡都是正序的冒泡排序,每次排序保证了最大的元素依次在后面排开,下面的版本是每次保证了最小元素的有序,即arr[0,i)是有序的
public static<E extends Comparable<E>> void SortReverse(E arr[]){
for (int i=0;i<arr.length-1;){
Integer flagIndex=arr.length;
//保证arr[0,i]是有序的
for (int j=arr.length-1;j>i;j--){
if (arr[j].compareTo(arr[j-1])<0){
Util.swap(arr,j,j-1);
flagIndex=j-1;
}
}
i=flagIndex;
}
}
全部代码整合的泛型设计:
public class BubbleSort {
public BubbleSort(){}
public static<E extends Comparable<E>> void Sort(E arr[]){
//循环n-1次
for (int i = 0; i < arr.length-1; i++) {
Boolean flag=false; //当进行一次没有位置交换说明数组是有序的
for (int j=0;j<arr.length-i-1;j++){
if (arr[j].compareTo(arr[j+1])>0){
Util.swap(arr,j,j+1);
flag=true;
}
}
if (!flag) break;
}
}
public static<E extends Comparable<E>> void bestSort(E arr[]){
//i不仅可以表示循环的次数,还可以表示已经排好序的元素个数
//因为每次循环结束之后arr[n-i,n)是有序的
for (int i = 0; i < arr.length-1; ) {
Integer lastSwapIndex=0;
for (int j=0;j<arr.length-i-1;j++){
if (arr[j].compareTo(arr[j+1])>0){
Util.swap(arr,j,j+1);
lastSwapIndex=j+1;
}
}
//下面的if语句可以直接省略,因为当没有进行交换的
// 时候,lastSwapIndex=arr.length,for循环就会停止了
// if (lastSwapIndex==0) break;
i=arr.length-lastSwapIndex;
}
}
//实现每次确定最小元素的位置
public static<E extends Comparable<E>> void SortReverse(E arr[]){
for (int i=0;i<arr.length-1;){
Integer flagIndex=arr.length;
for (int j=arr.length-1;j>i;j--){
if (arr[j].compareTo(arr[j-1])<0){
Util.swap(arr,j,j-1);
flagIndex=j-1;
}
}
i=flagIndex;
}
}
public static void main(String[] args) {
Integer arr[]=Util.getRandomArr();
//Integer arr[]={1,2,4,3};
BubbleSort.SortReverse(arr);
Util.Traverse(arr);
}
}