演算法導論Lecture 4 Quicksort

2021-08-30 21:05:52 字數 2927 閱讀 9314

第四課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)

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)

分析:在分析中我們假定陣列中所有元素都是不同的。首先是worst case。最壞情況會在輸入已經有序或者反序的情況下出現,也就是會使partition分割的子陣列中有乙個為空的情況下,記為0:n-1,這樣就有

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 ...