1. 程式人生 > 實用技巧 >演算法圖解學習筆記二

演算法圖解學習筆記二

演算法圖解學習筆記二

第四章  快速排序

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)