1. 程式人生 > 實用技巧 >關於氣泡排序和二分查詢

關於氣泡排序和二分查詢

關於氣泡排序和二分查詢的一些個人看法

1. 氣泡排序

    冒牌排序為什麼叫氣泡排序呢?是因為每次都會有一個較小的數不斷往陣列前方走(小到大排序),如同一個泡泡上升的過程,因此我們稱之為氣泡排序。先貼一下程式碼:

void Bubble_sort()
{
	for(int i = 1;i < n;i ++ )
	{
		for(int j = 1;j < n;j ++ )
		{
			if(a[j] > a[j + 1])
			{
				swap(a[j],a[j + 1]);
			}
		}
	}
}

    我們每次都選取數列中的第一個元素\(a[j]\)往後比較,若\(a[j+1]\)

大於\(a[j]\),則交換兩個數,每進行一次這樣的過程,都會使得陣列中的一個較大的數處於陣列後方。一共進行\(n\)次這樣的過程,所以會使\(n\)個數處於有序的狀態,於是就可以在\(O(n^2)\)的時間內排好這一列數。由於在\(a[j]\)\(a[j+1]\)相同時,不發生交換,所以氣泡排序還是一種穩定排序演算法。

2. 二分查詢(\(a\)陣列為單調遞增數列)

    二分查詢是確定一個元素在數列中的位置的演算法。什麼樣子的陣列能使用二分查詢呢?不如來看看二分查詢的程式碼:

int equal_dict(int x)
{
	while(l < r)
	{
		int mid = (l + r) >> 1;
		if(a[mid] >= x) r = mid;
		else l = mid + 1;
	}
	return a[l];
}

    先說結論:具有單調性的陣列才可以進行二分查詢。每次我們都有一個\(l\)\(r\),來表示我們要查詢的範圍,\(mid\)\(l\),\(r\)的中間值。如果以mid為下標的數大於了目標值\(x\),則下標為\(mid\)的數以後都是大於\(x\)的,所以\(x\)不可能位於\(mid\)右側,所以我們就選擇\(mid\)的左側,這個區間一定是\(x\)所在的區間。小於同理。如果數列不是有序的,則不能進行縮小區間的操作,無法找到\(x\)的位置。
    二分演算法充分利用了元素間的次序關係,採用分治策略。由於每次區間長度折半,所以時間複雜度為\(O(log_{2}{n})\)。發明二分演算法的大佬Knuth說,思路很簡單,細節是魔鬼。二分的細節很是重要,據說只有10%的程式設計師能寫對二分。所以二分要掌握自己的一套寫法,練熟練會即可。

寫在後面

排序演算法有很多種,大致可以分為以下三類:

  • 氣泡排序、插入排序、選擇排序
  • 堆排序、歸併排序、快速排序
  • 計數排序、基數排序、桶排序
        前兩類都是基於比較的排序演算法,第一類排序時間複雜度為\(O(n^2)\),第二類排序時間複雜度為\(O(nlog_n)\),資訊理論以證明,基於比較的排序演算法的時間複雜度下界為\(O(nlog_n)\),第二類演算法已經是最優的基於比較的排序演算法了
    第三類演算法換了一種思路,它們不直接比較大小,而是對被排序的數值採取按位劃分,分類對映等處理方式,其時間複雜度不僅與\(n\)有關,還與數值的大小範圍\(m\)有關。