無聊寫排序之 ---- 冒泡排序(Bubble Sort)

      排序是寫代碼中經常會遇到的一個問題,不管你是寫項目還是寫算法,經常會有sort的身影出現。當然排序的算法大大小小有很多種,也有現成的庫函數可以直接調用,而且效率比你自己寫的要高效很多倍。那爲什麼還要學排序呢,哈哈 各種排序的實現原理你還是要了解才能去更好的應用在不同的場景和高效高性能的編寫code。。。


     排序算法大的分類上分爲這麼幾類(我們這裏講的排序都是內排序):插入排序(直接插入排序算法 , 希爾排序), 選擇排序(簡單選擇排序, 堆排序), 交換排序(冒泡排序,  快速排序), 歸併排序(歸併排序)。上述7種排序算法也是我們最常見的幾種排序算法,今天我們講解最簡單的冒泡排序算法Bubble Sort。

冒泡排序(Bubble Sort):冒泡排序是一種交換排序,將兩兩相鄰的元素進行大小對比,若反序則交換兩個元素的位置, 否則進行下兩個相鄰元素。直到沒有反序的元素出現,則停止排序。冒泡算法在實現上有許多不一定的地方,我們先看最常見的一種寫法:

交換函數

void Swap(int arr[], int i, int j)
{
	arr[i] = arr[i] + arr[j];
	arr[j] = arr[i] - arr[j];
	arr[i] = arr[i] - arr[j];
}

void Bubble_sort_atypia(int arr[], int n)
{
	for (int i = 0; i < n; i++)
	{
		for (int j = i+1; j < n; j++)
		{
			if (arr[i] > arr[j])
			{
				Swap(arr, i, j); // 交換兩個值
			}
		}
	}
}

        這是最容易實現的一種方式, 將從頭開始的每一個元素都和他後面的每一個元素進行對比,這樣每次遍歷一次都有一個最小的元素被放置在前面的位置上(如下圖所示)。但是在嚴格意義上來講它並不是標準的冒泡排序,我們講冒泡排序是將兩個相鄰的元素進行對比和交換,而上述算法中除了每次遍歷的第一組值相鄰外其餘都不相鄰。而且還有一個缺陷:在將最小的數字冒泡到第一個位置的時候對次小的元素可能會換到最下面的位置。如:


在我們將1和2的順序排好後3這個次小的數字被換到了最後面,這種冒泡算法對於別的元素的排序沒有任何幫助,這種排序的效率會比較低,但是最容易書寫的。


讓我們來看標準的冒泡排序:

void Bubble_sort(int arr[], int n)
{
	for (int i = 0; i < n; i++)
	{
		for (int j = n-2; j >= i; j--)	// j是從後往前進行的
		{
			if (arr[j] > arr[j+1])		// 比較兩個相鄰的數據項
			{
				Swap(arr, j, j+1);		// 交換兩個相鄰的數據 
			}
		}
	}
}


     當i = 0時, j = n-2, 而比較的永遠都是k 和k+1兩個位置上的元素,也就真正實現了相鄰兩個元素的比較和交換,這樣每一次較小的元素都會想氣泡一樣冒出水面。

當我們把最小的元素1換到第一個位置的同時, 次小的元素2也被換到了更近的位置,這樣在每次排序的過程中對於那些未排序的元素也有幫助,當排序數量少的時候可能還看不出優勢來,當數據規模漸變漸大的時候這種優勢將會越來越明顯的體現出來。


冒泡排序的優化:

試想這樣一個問題:當給出的序列基本有序或者完全有序時, 上述的代碼會在排序完少數幾個序列後仍將繼續進行循環比較試圖尋找反序的序列進行排序,這樣雖然已經沒有再做交換了, 但是還是有很多無謂的比較出現,因爲此時序列已經有序了。我們改進這個部分,使用一個標誌變量來記錄上一次循環是否有交換出現,如果沒有則說明序列已經有序便可以結束排序。代碼如下:

void Bubble_sort_optimize(int arr[], int n)
{
	bool exchange_flag = true;
	for (int i = 0; i < n  && exchange_flag; i++) // 沒有交換直接退出
	{
		exchange_flag = false;
		for (int j = n-2; j >= i; j--)	
		{
			if (arr[j] > arr[j+1])		// 比較兩個相鄰的數據項
			{
				Swap(arr, j, j+1);		// 交換兩個相鄰的數據 
				exchange_flag = true;
			}
		}
	}
}

冒泡排序的時間複雜度:O(n^2)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章