基本思想
对当前还未排好序的范围内的全部数,自上而下对相邻的俩个数依次进行比较和调整,让较大的数下沉,较小的数往上冒。即:每当俩相邻的数比较后发现他们的排序与排序的要求相反时,就将他们交换。每次遍历都可确定一个最大值放到待排数组的末尾,下次遍历,对该最大值以及它之后的元素不再排序(已经排好)。
由于冒泡排序算法交换和比较的操作次数都与N2成正比,由于在大O表示法中,常数忽略不计,冒泡排序的时间复杂度为O(N2)。O(N2)的时间复杂度是一个比较糟糕的结果,尤其在数据量很大的情况下。所以冒泡排序通常不会用于实际应用。
冒泡排序算法相比于其他排序算法的唯一显著优势是可以检测输入序列是否已经是排序的。
Java版本实现
public void bubbleSort1(T a[]) {
int n = a.length;
int count = 1;
for(int i = 0 ; i < n - 1 ; i ++ ) {
boolean flag = false;
for(int j = 1 ; j < n - i; j ++) {
if(a[j].compareTo(a[j - 1]) < 0) {
T temp = a[j - 1];
a[j - 1] = a[j];
a[j] = temp;
if(!flag)
flag = true;
}
}
if(!flag)
break;
System.out.print("第" + count + "轮排序:");
display(a);
count ++;
}
}
传统的冒泡算法每次排序只确定了最大值,我们可以在每次循环之中进行正反两次冒泡,分别找到最大值和最小值,如此可使排序的轮数减少一半。
改进代码如下:
//优化版本
public void bubbleSort2(T a[]) {
int n = a.length;
int low = 0;
int high = n - 1;
int count = 1;
while(low < high) {
boolean flag = false;
//正向冒泡,找到最大值
for(int i = low ; i < high ; i ++) {
if(a[i].compareTo(a[i + 1]) > 0 ) {
T temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
if(!flag)
flag = true;
}
}
--high;
//逆向冒泡,找到最小值
for(int j = high ; j > low ; j --)
if(a[j].compareTo(a[j - 1]) < 0) {
T temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
if(!flag)
flag = true;
}
++low;
if(!flag)
break;
System.out.print("第" + count + "轮排序:");
display(a);
count ++;
}
}