快速排序:原始碼(C++)--虛擬碼--時間複雜度解析
阿新 • • 發佈:2019-01-30
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 */ }