1. 程式人生 > >氣泡排序 知識點小結

氣泡排序 知識點小結

氣泡排序,是指計算機的一種排序方法,它的時間複雜度為O(n^2),雖然不及堆排序、快速排序的O(nlogn,底數為2),但是有兩個優點:1.“程式設計複雜度”很低,很容易寫出程式碼;2.具有穩定性,這裡的穩定性是指原序列中相同元素的相對順序仍然保持到排序後的序列,而堆排序、快速排序均不具有穩定性。不過,一路、二路歸併排序、不平衡二叉樹排序的速度均比氣泡排序快,且具有穩定性,但速度不及堆排序、快速排序。氣泡排序是經過n-1趟子排序完成的,第i趟子排序從第1個數至第n-i個數,若第i個數比後一個數大(則升序,小則降序)則交換兩數。

(氣泡排序有正向冒泡,也有反向冒泡,原理都一樣,只不過在排序的時候,前者是將最小的數前移,後者是將最大的數後移。本文以正向冒泡為主)

氣泡排序的基本概念是:依次比較相鄰的兩個數,將大數放在前面,小數放在後面。即首先比較第1個和第2個數,將大數放前,小數放後。然後比較第2個數和第3個數,將大數放前,小數放後,如此繼續,直至比較最後兩個數,將大數放前,小數放後,此時第一趟結束,在最後的數必是所有數中的最小數。重複以上過程,仍從第一對數開始比較(因為可能由於第2個數和第3個數的交換,使得第1個數不再大於第2個數),將大數放前,小數放後,一直比較到最小數前的一對相鄰數,將大數放前,小數放後,第二趟結束,在倒數第二個數中得到一個新的最小數。如此下去,直至最終完成排序。


排序過程


  設想被排序的陣列R[1..N]垂直豎立,將每個資料元素看作有重量的氣泡,根據輕氣泡不能在重氣泡之下的原則,從下往上掃描陣列R,凡掃描到違反本原則的輕氣泡,就使其向上"漂浮",如此反覆進行,直至最後任何兩個氣泡都是輕者在上,重者在下為止。

程式碼示例:

//氣泡排序


#include<iostream>

using namespace std;

void BubbleSort(int *a,int n){
	for(int i=0;i<n;i++)//從第一個元素開始,不斷的縮小待排序的序列
		for(int j=n;j>i;j--)//反向檢測,檢測是否逆序
			if(a[j] < a[j-1])//條件判斷是否需要逆序
				swap(a[j-1],a[j]);//交換兩數
}

void main(){
	int a[]={44,3,1,4,6,53,5};
	BubbleSort(a,6);
	for(int i=0;i<7;i++)
		cout<<a[i]<<" ";
	cout<<endl;

}

起泡排序中,第i趟起泡中需要執行i-1次比較和交換。因此 i 從0 到 n-1 ,執行的比較操作的次數為:

( n - 1) + ( n - 2 ) + ( n - 3 ) + ( n - 4 ) + ...+ 2 + 1 = n ( n - 1 ) / 2 = O( n ^ 2) .

從排序的執行過程中我們可以看到基本的起泡排序的資料比較次數與輸入序列中待排序元素的起始排序有關,但資料的交換次數與各待排序元素的初始位置排列有關,它與逆序的發生有關,最好的情況是可能一次也不交換,最差的情況下,每次比較都需要交換。

我們可以考慮對起泡排序演算法的改進。具體的某一個待排序元素序列可能不需要執行n - 1 次趟 排序就能全部排好。為此 ,我們可以再演算法中加上一個標記 flag ,用來標示本趟起泡結果是否發生了逆序 和 交換 。如果沒有發生交換,則 flag = false ,表示全部的元素都已經排好了,可以進行終止處理,否則繼續進行排序。

改進後的程式碼如下:

//氣泡排序


#include<iostream>

using namespace std;

void BubbleSort(int *a,int n){
	bool flag;
	for(int i=0;i<n;i++)//從第一個元素開始,不斷的縮小待排序的序列
	{	flag = true;
		for(int j=n;j>i;j--)//反向檢測,檢測是否逆序
			if(a[j] < a[j-1])//條件判斷是否需要逆序
			{	
				swap(a[j-1],a[j]);//交換兩數
				flag = false;			
			}	
		if(flag == true)
			return ;
	}
}

void main(){
	int a[]={44,3,1,4,6,53,5};
	BubbleSort(a,6);
	for(int i=0;i<7;i++)
		cout<<a[i]<<" ";
	cout<<endl;

}