第四課80多分鐘,好長啊...內容很多,但是leiserson教授講得既快又好!
快速排序(quicksort)是c. a. r. hoare於2023年發明,當時他正在莫斯科大學(soviet union, 前蘇聯吧)作訪問學生。在乙個國家物理實驗室的機器翻譯專案裡,為了能更快的匹配乙個已排序的俄英字典,他開發了這個演算法來排序要翻譯的單詞。
快速排序也是使用的分治法的思想。同時也是個in place的演算法,這個詞意思是指就地進行的演算法,不需要額外的儲存,想了半天也沒想到好的中文對應的字,後來去看了下中文版的書才知道,原來是翻成「就地」,很貼切啊!經過改進的快速排序也是很實用的排序演算法,是當前世界上使用最多的排序演算法之一。
分治法步驟:
所以關鍵步驟就是這個partition:
partition(a, p, q)這個迴圈的不變數可以用下面的圖表示:x := a[p]
i := p
for j := p+1 to q
do if a[j] <= x
then i := i+1
swap(a[i], a[j])
swap(a[p], a[i])
return i
x<=x
>=x
?
p i j q
對於有n個元素的陣列的來說,partition的漸近執行時間為theta(n)。
主程式quicksort很簡單:
quicksort(a, p, q)分析:在分析中我們假定陣列中所有元素都是不同的。首先是worst case。最壞情況會在輸入已經有序或者反序的情況下出現,也就是會使partition分割的子陣列中有乙個為空的情況下,記為0:n-1,這樣就有if p < q
then r := partition(a, p, q)
quicksort(a, p, r-1)
quicksort(a, r+1, q)
init call: quicksort(a, 1, n)
t(n) = t(0) + t(n-1) + theta(n) = theta(n^2)。
最壞情況下並沒有比insertion sort好!如果你畫出上面這個式子的遞迴樹會發現這棵是高度的不平衡的。我們再來看看最好情況,如果我們很幸運,每次partition都能將陣列分成兩個長度相等的子陣列,也就是(n-1)/2 : (n-1)/2。那麼有
t(n) = 2t((n-1)/2) + theta(n) = theta(nlgn)。這也是quicksort的下界。
再假定每次分割都是1/10 : 9/10, t(n) = t(n/10) + t(9n/10) + theta(n),可以畫出這個遞迴樹,或者用替換法都能解出t(n) = theta(nlgn)。仍然是nlgn!
或者假定既「幸運」又「不幸運」:
l(n) = 2u(n/2) + theta(n) // 幸運,分割成n/2 : n/2
u(n) = l(n-1) + theta(n) // 不幸運,分割成0 : n-1
還是可以解得l(n) = 2(l(n/2-1) + theta(n/2)) + theta(n) = theta(nlgn)。
也就是,就算有一些步驟是「不幸運」的,我們仍然能得到theta(nlgn)的漸近執行時間。所以也就有了:
隨機版的快速排序(randomized quicksort)。
通常的做法是隨機地選擇主元(pivot)。
隨機演算法的分析一般都比較難。這裡的分析都很直觀也都是很基礎的內容,但是要想到這些東西卻不是那容易的,你需要一定的知識體系!
t(n)為漸近執行時間,其期望值(expectation)為e[t(n)],我們希望對所有的輸入,找出這個期望值。
對k=0,1,2,...,n-1,我們定義乙個0-1隨機變數x_k:
x_k = 1 // 如果partition分割成k:n-k-1
0 // 如果不是的話
x_k的期望e[x_k] = 1*pr + 0*pr = pr = 1/n。而t(n)可以寫成:
這個遞迴式有n種情況,我們可以借助0-1變數來處理:
這樣e[t(n)]可以寫成:
因為e[t(0)]=theta(1),e[t(1)]=theta(1),為了計算方便,將最後乙個和式中的k=0,k=1吸收到theta(n)中去:
剩下的就是使用替換法證明e[t(n)] <= anlgn,a>0。這裡可以看出我們將k=0,1吸收到theta(n)中的好處,因為lg0無法處理,lg1=0。我們還需要用到乙個事實,它的證明需要一點點技巧,也需要一定的篇幅,這裡先給出來直接使用:
將e[t(k)]代入e[t(n)]可得:
第二個不等式用到了上面的事實。所以e[t(n)] = theta(nlgn)。即使不需要調整優化,快速排序也會比一般的排序快上3到4倍,而實用中的快速排序通常會做一些調整,比如quicksort主程式最後一步是尾遞迴,或者對較小的陣列使用直接的排序而不再使用遞迴等等。
另外,robert sedgewick在2023年的ph.d**就是quicksort (quicksort. ph.d. thesis. stanford computer science report stan-cs-75-492. stanford, ca: stanford university, may 1975.) 還有他在2023年發在acm上的"implementing quicksort programs" (implementing quicksort programs. comm. acm21, 847-857, 1978.) donald knuth的taocp第三卷sorting and searching等等。總之快速排序的材料很多。wiki上的也值得一讀(
演算法導論Lecture 2 解遞迴
這個lecture包括了clrs中的chapter3 chapter4兩章內容 漸近性標記和解遞迴。erik demaine主講。gee 每次看到erik的一頭 秀髮 跟leiserson教授的光頭就想笑笑,別誤會,erik s a man.解遞迴 解遞迴常用的有三種方法 替換法 substitut...
演算法導論 第4章
這一章,就乙個主題,什麼是遞迴式?如何求解遞迴式?遞迴式,就是乙個函式,自己呼叫自己,但是有乙個最基本的情況,這種情況下,它就會自動返回跳出遞迴。用什麼方法?3種方法 1.代換法 2.遞迴樹方法 3.主方法 關於代換法 乙個字,猜,也就是你會蒙?怎麼蒙?需要你的經驗。也就是說,有經驗的人,一看就知道...
演算法導論(4) 順序統計量
1.最大值與最小值 將一對輸入元素相互進行比較,然後把較小的與當前的最小值比較,把較大的與當前最大值比較,這樣每兩個元素比較3次,最多需要3 n 2次比較可以同時找到一組輸入元素中的最大值與最小值。2.順序統計量 乙個n個元素組成的集合中,第i個順序統計量是該集合中第i小的元素。中位數是i n 1 ...