冒泡排序(Bubble Sort)
1.傳統的冒泡排序演算法
(1)演算法思想
當進行升序的冒泡排序時,則從後往前,依次比較相鄰的兩個數,若前面的數大於後面的數,則進行交換。第一次迴圈結束後,待排序序列A[1..n]中的最小元素被交換到A[1]位置。經過n-1次迴圈,即可完成對A的排序。
若對A=(49, 38, 65, 97, 76, 13, 27, 49)進行冒泡排序,第1次迴圈元素的交換過程過程如下所示(雙向箭頭:交換):
冒泡排序的整個過程如下圖所示:
(2)虛擬碼
BUBBLE-SORT(A)
1 for i ← 1 to length[A] - 1
2 do for j ← downto i + 1
3 do if A[j]<A[j-1]
4 then exchange A[j] A[j-1]
(3)代碼實現
void BubbleSort_1(int A[],int n){ int i,j; for(i=0;i<n;i++) { for(j=n-1;j>=i+1;j--) { if(A[j]<A[j-1]) { int temp=A[j]; A[j]=A[j-1]; A[j-1]=temp; } } }}
(4)演算法分析
a.冒泡的時間複雜度為:Θ(n^2)。
b.冒泡排序是一種原地排序。
c.冒泡排序是一種穩定排序。
2.冒泡演算法的改進
(1)改進(一):設定交換標識
從上面圖示的例子可以看出,當第4次迴圈結束後,數組A就已經是有序的了,後面的迴圈不再進行交換操作,但是傳統的冒泡排序仍然進行後面的迴圈。這裡可以設定一個交換標識(change_flag),當一次迴圈中沒有發生任何交換操作,則停止後面的迴圈,這樣能減少迴圈的次數。改進後的實現如下:
void BubbleSort_2(int A[],int n){ int i,j; bool change_flag=true; for(i=0;i<n&&change_flag;i++) //只有當上次迴圈中有交換髮生,才繼續進行本次的迴圈 { change_flag=false; //每次迴圈開始時,設定change_flag為false for(j=n-1;j>=i+1;j--) { if(A[j]<A[j-1]) { int temp=A[j]; A[j]=A[j-1]; A[j-1]=temp; change_flag=true; //有交換進行,change_flag設定為true } } }} (2)改進(二):雙向冒泡排序
雙向冒泡排序即在每趟排序中進行正向和反向兩遍冒泡的方法一次可以得到兩個最終值(最大者和最小者) , 從而使排序趟數幾乎減少了一半。具體實現如下:
void BubbleSort_3(int A[],int n){ int low=0; int high=n-1; while(low<high) { int j; for(j=low;j<high;j++) //正向冒泡,找最大值 { if(A[j]>A[j+1]) { int temp=A[j]; A[j]=A[j+1]; A[j+1]=temp; } } high--; for(j=high;j>low;j--) //反向冒泡,找最小值 { if(A[j]<A[j-1]) { int temp=A[j]; A[j]=A[j-1]; A[j-1]=temp; } } low++; }}