演算法圖解學習筆記二
演算法圖解學習筆記二
第四章 快速排序
4.1 分而治之(D&C) -->解決問題的思路
1.例子:農場主分地問題: 將一塊地均勻地分成方塊
怎麼將一塊地均勻地分成方塊,且確保方塊是最大的-->使用D&C策略
(1).找出來基線條件,這種條件必須儘可能簡單
(2).不斷將問題分解,直到符合基線條件
first -->找基線條件 最簡單的情況是:一條邊的長度是另一條邊的整數倍
then--->找遞迴條件,我們先找這塊地容納的最大方塊
最初要劃分的土地為1680*640m
可從這裡劃分出兩個640*640m的方塊,同時餘下一塊400*640m的方塊
由歐幾里得演算法 -->使用於這小塊地的最大方塊也是整個地的最大方塊
問題轉化為了均勻劃分640*400土地的問題
下面使用同樣的演算法,可劃出的最大方塊為400*400,剩下一塊更小的土地240*400m
-->240*240m 240*160m
-->160*160m 160*80m(基線條件)
-->80*80m 所以適應的最大方塊為80*80m
2.例子二:怎麼用遞迴函式來實現陣列元素相加 2 4 6
提示:編寫涉及陣列的遞迴函式時,基線條件通常是陣列為空或者只包含一個元素,陷入困境時,請檢查基線條件是不是這樣的。
3.函數語言程式設計:
如Haskell等函數語言程式設計語言無迴圈,只能用遞迴寫這種函式。--->理解遞迴的思想有利於學習函數語言程式設計語言
sum[]=0 //基線條件
sum[x:xs]=x+(sum xs) //遞迴條件
或者用Haskell中的if語句編寫
sum arr = if arr ==[]
then 0
else (head arr)+(sum(tail arr))
4.2 快速排序 --->C標準庫中的函式qsort實現即快排 D&C+歸納證明
1.基線條件:陣列為空或只包含一個元素
2.遞迴條件:
(1).找基準值/主元(pivot) -->第一位,中間數,最後一位的中位數,並排序交換位置,把主元放到倒數第二個
(2).分割槽:
a.一個由所有小於主元的數字組成的子陣列
b.基準值
c.一個由大於主元數字組成的子陣列
(3)對左右分割槽進行排序
3.實現程式碼
def quicksort(array): if len(array)<2: #基線條件 return array else pivot=array[0]; less=[i for i in array[1:] if i<=pivot] greater=[i for i in array[1:] if i>pivot] return quicksort(less)+[pivot]+quicksort(greater) print quicksort([10,5,2,3])
4.3 再談大O表示法
1.快排的速度取決於選擇的基準值,平均執行時間為O(nlog n),最糟糕的情況就是O(n*2) ,遇到平均情況的概率要比最糟糕情況大很多。
2.比較歸併排序和快速排序
在O表示法中,n可能實際為c*n,c為固定的時間量(一些時候這個常量很重要)
快排的C比合並查詢要小,所以如果他們的執行時間都為O(nlog n),快排的速度會更快。
3.平均情況和最糟糕情況:
每次將第一個值作為主元,對1,2,3,4,5,6,7,8進行排序,呼叫棧的長度為8,陣列並未對半分,其中一個子陣列始終為空。---->最糟糕情況 棧長O(n)
每次將陣列對半分---->呼叫棧的長度為4 最佳情況也是平均情況(隨機去一個主元的平均執行時間) 棧長O(log n)---層數
完成每一層的時間都是O(n)