【資料結構與演算法】內部排序之二:氣泡排序和選擇排序(改進優化,附完整原始碼)

蘭亭風雨發表於2014-03-02

轉載請註明出處:http://blog.csdn.net/ns_code/article/details/20065107


前言

    之所以把氣泡排序和選擇排序放在一起,是因為二者的實現程式碼很相似,而且都是最基本的排序方式,非常容易理解和實現。當然,如果僅僅是為了講述這兩種排序方式,那也根本沒必要寫這篇博文了。和上篇博文一樣,我會在氣泡排序和選擇排序原始程式碼的基礎上給出一些改進和優化,這才是本文的重點所在。

原始氣泡排序

    氣泡排序的思想很簡單,如果要求排序後序列中元素按照從小到大的順序排列,則氣泡排序的步驟如下:

    1、依次比較序列中相鄰的兩個元素,將較大的放在後面,這樣一趟比較後,最大的元素就放在了最後的一個位置;

    2、再依次比較相鄰的兩個元素,將第二大的元素最終放到倒數第二個位置;

    3、依次迴圈,直到最小的元素放在了第一個位置,排序完成。

    根據以上思想,很容易寫出程式碼:

/*
氣泡排序後的順序為從小到大
*/
void Bubble_Sort(int *arr,int len)
{
	int i,j,exchange;
	for(i=0;i<len-1;i++)
		for(j=0;j<len-i-1;j++)
			if(arr[j] > arr[j+1])
			{
				exchange = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = exchange;
			}
}

改進氣泡排序 

    我們回過頭來再來看上面氣泡排序的思想,無論原始序列的排序是怎樣的(哪怕已經是從小到大排好的),它都要進行n-1趟比較,每趟比較又要進行n-i-1次相鄰元素間的比較(i為從0開始計的第i趟比較),而實際上,很有可能還沒有進行第n-1趟比較,已經完成了排序,這時候後面的幾趟比較就顯得多餘了,基於此,我們可以做如下改進:設定一個標誌位,如果某一趟有元素髮生交換,則為true,繼續下一趟比較,否則,說明排序已經完成,則標誌位為false,退出迴圈。程式碼實現如下:

/*
氣泡排序後的順序為從小到大
*/
void Bubble_Sort(int *arr,int len)
{
	int i,j,exchange;
	bool flag = true;   //增設標誌位,判斷是否已經完成排序
	for(i=0; i<len-1 && flag; i++)
	{
		flag = false;
		for(j=0;j<len-i-1;j++)
			if(arr[j] > arr[j+1])
			{	//如果本趟比較沒有資料發生交換,說明排序已經完成
				//則flag一直為false,從而退出迴圈,不再進行下一趟的比較
				exchange = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = exchange;
				flag = true;
			}
	}
}

直接選擇排序

    直接選擇排序的思想也很簡單,以排序從小到大為例,如下:

    1、從第一個元素開始,選出一個最小的元素與第一個元素互換;

    2、繼續從第二個元素開始,向後選出最小的元素,與第二個元素互換;

    3、依次迴圈執行,直到最大的元素放在了最後一個位置上,排序完成。

    我們可以將第一個元素分別與後面的元素進行比較,遇到更小的,就交換,這樣一趟比較下來,第一個元素儲存就是最小值,而後再從第二個元素開似乎,依次與後面的元素比較,遇到更小的,就交換,這樣,第二趟比較下來,第二個元素儲存的就是第二小的值。。。依次迴圈執行,直到完成排序。按照這樣的思路,實現程式碼如下:

/*
第一種形式的選擇排序
選擇排序後的順序為從小到大
*/
void Select_Sort1(int *arr,int len)
{
	int i,j;
	for(i=0;i<len;i++)
		for(j=i+1;j<len;j++)
			if(arr[i] > arr[j])
			{
				int exchange = arr[i];
				arr[i] = arr[j];
				arr[j] = exchange;
			}
}

改進選擇排序

    但是我們上篇文章中提到過,在排序中應該儘量避免較多的和元素互換操作,而這裡每比較一次,如果遇到更小的,就要互換一次元素。為了減少元素互換操作,我們可以在每次比較後不直接進行交換,將較小的元素的位置序號記錄下來,這樣一趟比較之後,就會得到最小元素的位置,如果最小值的位置發生了改變,再將該位置的元素與第一個元素互換,依次類推。。。這樣每一趟比較完成後最多隻需執行一次元素互換的操作。實現程式碼如下:

/*
第二種形式的選擇排序,減少了元素互換的操作
選擇排序後的順序為從小到大
*/
void Select_Sort2(int *arr,int len)
{
	int i,j,min;
	for(i=0;i<len;i++)
	{
		min = i;	//用來記錄每一趟比較的最小值的位置
		for(j=i+1;j<len;j++)
			if(arr[min] > arr[j])
				min = j;	 //僅記錄最小值的位置
		//如果最小值的位置發生了變化,
		//則最後執行一次元素互換的操作
		if(min != i)
		{
			int exchange = arr[i];
			arr[i] = arr[min];
			arr[min] = exchange;
		}
	}
}

總結

    氣泡排序和選擇排序都是最基本的排序演算法,平均時間複雜度都為O(n*n),排序元素個數較少時,適合使用,遇到大資料量時,最好選用其他排序演算法。

完整原始碼

    完整的C語言實現程式碼下載地址:http://download.csdn.net/detail/mmc_maodun/6970951




相關文章