1. 程式人生 > >快速排序:原始碼(C++)--虛擬碼--時間複雜度解析

快速排序:原始碼(C++)--虛擬碼--時間複雜度解析

namespace htx{
	//////////////////1.快速排序////////////////////////
	//<1>原始碼  <2>虛擬碼  <3>時間複雜度分析
	//--------<1>原始碼---------
	//如果陣列的元素不是基本資料型別,而是物件,那麼對應的類需要過載
	//快速排序:從小到大 1->2
	template<class T>
	void quicksort12(T *A,int p,int r)
	{
		if(p < r)
		{
			int q = no_partition12(A,p,r);
			quicksort12(A,p,q-1);
			quicksort12(A,q+1,r);
		}
	}

	template<class T>
	int no_partition12(T *A,int p,int r)
	{
		T x = A[r];
		int i = p - 1;
		for(int j = p; j < r; j++)
		{
			//如果陣列A的元素是類物件,
			//那麼只有當該類過載了“<=”運算子後才能使用本模板
			//(也就是隻有當該類過載了“<=”運算子後才能通過編譯),下同
			if(A[j] <= x)
			{
				i = i + 1;
				exchange(A[i],A[j]);
			}
		}
		exchange(A[i+1],A[r]);


		return i+1;
	}
	//快速排序:從大到小 2->1
	template<class T>
	void quicksort21(T *A,int p,int r)
	{
		if(p < r)
		{
			int q = no_partition21(A,p,r);
			quicksort21(A,p,q-1);
			quicksort21(A,q+1,r);
		}
	}

	template<class T>
	int no_partition21(T *A,int p,int r)
	{
		T x = A[r];
		int i = p - 1;
		for(int j = p; j < r; j++)
		{
			if(A[j] >= x)
			{
				i = i + 1;
				exchange(A[i],A[j]);
			}
		}
		exchange(A[i+1],A[r]);
		return i+1;
	}

	//元素交換
	template<class T>
	void exchange(T &a,T &b)
	{
		//如果出現數組越界,是不能使用try-catch來捕捉的
		T m = a;
		a = b;
		b = m;
	}

/*
<p>呼叫簡例:</p><p>array[10];</p><p>htx::quicksort12(array,0,9);</p>
*/

	/*--------<2>虛擬碼---------
	QUICKSORT(A,p,r)
	if p < r
	q = PARTITION(A,p,r)
	QUICKSORT(A,p,q-1)
	QUICKSORT(A,q+1,r)

	PARTITION(A,p,r)
		x = A [ r ]
		i = p - 1
		for j = p to r - 1
			if A[ j ] <= x
				i = i + 1
				exchange A [ i ] with A [ j ]
		exchange A [ i+1 ] with A [ r ]
		return i + 1
	*/

	/*--------<3>時間複雜度分析---------
	最好:O(n) = nlog(2)n
	平均:O(n) = nlog(2)n
	最壞:O(n) = n^2

	提示:可以按照描述自己畫一下圖
	1.根據上述虛擬碼可知,快速排序函式是分兩路遞迴的函式
	2.那麼將這個函式的遞迴路徑畫成二叉樹的形式,設同一個函式體裡面的兩個子遞迴路徑是同一層,即二叉樹的兩個子節點
	3.同一父節點下的兩個子節點就是同一個函式體內的兩個遞迴呼叫的“代價”(就是花多少時間)
	4.現在,假設“所有”父節點下的兩個子節點的代價是成比例的,本例設為 1:9
	5.有了比例(1:9),我們就可以算出這個二叉樹的高度了,假設為 h
	6.假設陣列有n個元素,那麼根節點的值就是n,即第一次迴圈的代價是c*n(c是常數,下同)
	7.而位於末端的所有子節點的代價“至少”為1(有可能是2),因為PARTITION的迴圈次數至少為1
	8.那麼 n * (9/10)^h = 1  得到 h = log(10/9)n    (如 log(a)b : 以a為底b的對數)
	9.而二叉樹每一層的代價和 <= c*n ,那麼 總代價 = c*n*log(10/9)n
	10.那麼再在最好的情況下的比例是1:1,此時的 總代價 = c * n * log(2/1)n = c*n*log(2)n = nlog(2)n
	11.所以最好的情況下是 O(n) = nlog(2)n;

	12.如果你給的待排序陣列資料是隨機的,那麼一直髮生1:9這樣懸殊的比例的概率是很小的。
	13.也就是說比1:9的情況好,那麼平均情況下就是接近 nlog(2)n 了。

	14.至於最壞的情況,這裡給個例子: 2 3 4 5 6 1 ,按照程式碼執行,代價為 5 4 3 2 1
	15.寫成公式: (1+(n-1)) * n / 2 = n^2/2  所以 最壞的情況下 O(n) = n^2
	*/

}