排序演算法——氣泡排序

鴨脖發表於2013-05-05

氣泡排序的核心是將被排序的記錄陣列R[1..n]垂直排列,每個記錄R[i]看作是重量為R[i].key的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描陣列R:凡掃描到違反本原則的輕氣泡,就使其向上"飄浮"。如此反覆進行,直到最後任何兩個氣泡都是輕者在上,重者在下為止。


記憶的時候,你就把陣列頭部朝下放著,然後從底部開始往上冒泡。但是為了好程式設計,並不是盯著那一個泡泡不放的,而是反正最後一共要進行n(n-1)次比較,所以我最後只要能把這個次數比較夠就行了,所以先將頭部的一個元素和其他所有位置的元素進行比較,如果發現頭部比其他輕,那麼就往上冒。你也可以倒過來編寫程式,但是要記住:

這個演算法是基於位置比較和元素交換的。快排也是基於元素交換的。書上說的時間複雜度應該是把每次交換看成了O(1)


下面我寫了一個程式實現了氣泡排序:

void bubbleSort(int* a,int n){
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(a[i]>a[j]){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
}


當然上述演算法我並沒有很好的模擬出冒泡的過程,因為我雖然是基於元素交換,並且也交換了一定的次數,但是我交換的過程卻不是基於相鄰元素的,所以這也就造成了我們的演算法不是特別的形象,因而我們要改成基於相鄰元素交換的程式:


void bubbleSort2(int* a,int n){
int i,j,last;
i = n-1;
while(i>0){
last = 0;
for(j=0;j<i;j++){
if(a[j+1]<a[j]){

//swap items
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;

//set the value of j
last = j;
}
}
i = last;
}
}

但是親愛的讀者,你們讀到這裡可能就有點迷糊了,其實我的第一個程式是錯誤的!這是為什麼呢?


我們知道分析一個演算法就要分析它的時間複雜度,所以我們不妨來分別分析一下兩個演算法的時間複雜度吧,而且這樣的分析都是從最好情況和最差情況兩個方面來進行分析的。


第一個演算法在最好情況下(初始序列已有序),需要進行n(n-1)/2次比較,因而最好情況下時間複雜度是O(n^2).最差情況下,不僅需要n(n-1)/2次比較,還需要3n(n-1)/2次移動,所以最壞情況下時間複雜度是O(n^2)。其實它更類似與簡單選擇排序。


我們再來看一下第二個演算法。最好情況下只需要進行一趟排序,進行(n-1)次比較,因此最好情況下的時間複雜度是O(n).最壞情況下和上述演算法一樣,為O(n^2)


因此我們可以看出,上述兩種演算法,在最壞情況下的演算法時間複雜度是一樣的,但是在最好情況下,兩者的時間複雜度卻相差了一個數量級。因此,第一個演算法在實現上是不合理的,儘管它能夠實現我們所希望的排序效果。

相關文章