麻省理工公開課《算法導論》學習筆記:第一講

主題:簡介課程,漸近概念的大局觀,插入排序和歸併排序,遞歸式函數時間分析(遞歸樹方法)算法

教材:《算法導論》安全

收穫:很感動地看到算法分析那個log(n)是爲何出現了,更深層還要聽第二講,若不是由於要準備SAS,巴不得立刻看。ide

內容:模塊化

1 何爲算法分析?函數

      計算機程序運行性能和存儲空間的理論分析,叫算法分析。也就是關注2點:1 性能,就是程序跑得快不快; 2 存儲空間,即佔用了多大的內存。可是主要仍是關注性能。(多是由於時間就是金錢吧,並且如今計算機硬件發展速度還不錯)性能

 

2 比性能更加劇要的因素都有哪些?學習

好比成本,正確性,功能特徵(features),用戶用好,模塊化性等等。idea

 

3 那爲什麼還學習算法和性能?spa

很妙的引入方法,你都說了上面那些東西比性能還重要,那尼瑪幹嗎還要學習算法?設計

學習算法的緣由:

A performance measures the line between the feasible and the infeasible.

對於不少比性能更重要的因素,其實他們跟性能是密切相關的,好比用戶用好,就須要你的程序響應時間控制在必定範圍內。算法老是處在解決問題的最前沿。

B algorithms give us a language for talking about program behavior.

算法給出了程序行爲的描述。

其實形象的比喻就是:水,食物這些東西都比錢重要,你爲何還須要錢?算法就像經濟社會中的「貨幣」,它給出了衡量的通常標準。好比你付出了性能來追求安全穩健性,用戶友好性等等。

好比JAVA程序一直很流行,其實它的性能比起C語言要差3倍多,可是因爲它自己的面向對象,異常機制等緣由,使得人們仍是很願意犧牲性能來追求可拓展性,安全性這些東東。我的的理解就是,好比在軟件設計中,你要着重追求某些方面,那在哪一種程度範圍內是能夠接受的呢?性能就是一個標準,好比犧牲3倍性能能夠接受,10倍就不行。

C tons of fun

追求速度老是頗有趣的,因此人們纔會熱衷於賽車,火箭等東西。

 

4 引入插入排序

插入排序(Insertion Sort)

4.1 描述

輸入 A[1…n],要輸出 A’[1,…n],使得A’中的元素按升序排序,也就是a’(1)<=a’(2)<=a’(3)…

4.2 僞代碼:

For j=2 to n

{

  Do key=a[j]

     i=j-1;

While i>0 and a[i]>key

Do a[i+1]=a[i]

     I=i-1;

}

  A[i+1]=key

}

4.3 舉例:

1 7 3 6 4 20 13 9

T1:看第二個元素,7,比1大,放在第二位

T2:看第三個元素,3,比7小,把7放到第三位,3再跟1 比較,比1大,因此3放在第二位,結果1 3 7

T3:相似,分析6,結果1 3 6 7

T4..

T7:1 3 4 6 7 9 13 20

4.4 本質:

每次循環後前面已經排好序的部分保持不變(這裏的不變應該是指不用管了,而不是位置絕對不變),每次循環的目的是完成增量,使得已經排序的長度+1

 

5 經過插入排序,看運行時間依賴哪些因素,引入算法分析的漸近分析符號

5.1 運行時間依賴因素

A 輸入的數列,若是已經排好序,工做量近似爲0,而若是是逆序的,工做量最大

B 輸入的數列規模n。6個數VS 6億個數,因此後續的運行時間分析時,咱們把時間當作是n的函數

5.2 T(n)引入

通常咱們都想知道運行時間的下屆,就是最差的狀況,這樣子對用戶是一個保證,你能夠跟人家說這個程序最多不超過3s,可是你不會說最少要3s吧,天知道最好3s,最差要多久,說不定是一生。

因此在算法分析中,咱們通常是作最壞狀況分析,能夠用T(n)表示最長的運行時間,

T(n)is the max time on any input size n.

有時候咱們也討論平均狀況。此時T(n) is the expected time over all input size n.也就是T(N)表示指望時間。

(什麼是指望時間,數學上的公式是每種輸入運行時間*每種輸入出現的機率,通俗來說就是加權平均。)

那麼每種輸入出現的機率是多大呢?咱們假設一種統計分佈:均勻分佈,固然也能夠選擇其餘分佈。均勻分佈,也就是說,每種輸入出現的機率是同樣的。

最好狀況分析,這個是假象,通常是拿來忽悠人的。沒什麼用。

運行時間依賴於具體的機器,因此通常分析的時候是考慮相對速度,也就是在同一臺機器上的運行速度。(相反的就是絕對速度,也就是在不一樣機器上作比較)

 

6 算法的大局觀:The Big idea of algorithm——漸近分析

6.1 基本思路是:

忽略掉那些依賴於機器的常量(好比某條具體操做運行時間,如賦值操做),並且,不是去檢查實際運行時間,而是關注運行時間的增加。什麼意思呢?就是關注的是當輸入規模n——》無窮時,T(n)是什麼狀況,而不是說n=10的時候的詳細比較。

6.2 具體

漸近符號:Θ(n)

運算法則:對於一個公式,棄去它的低階項,並忽略前面的常數因子。好比

Θ(3n^3+90n^2-5n+69)=Θ(n^3)

簡單吧!

其實Θ(n)是有嚴格的數學定義的(下節課再一塊兒講),因此算法導論這門課既是講數學,也是講計算機科學的。

6.3 數學與工程的trade-offs

從圖中(這個圖畫得不是通常的醜)能夠看出,當n0趨於無窮時,Θ(n2)<<Θ(n3)

有時候交點n0太大,計算機沒法運行,因此咱們有時會對一些相對低速算法感興趣。應該就是理論與實際的妥協trade-offs。

 

7 插入排序運行時間分析

 插入排序最壞狀況:

T(n)=2+3+…+n=(2+n)(n-1)/2=Θ(n^2)

插入排序算不算快?

對於較小的n,還算是很快的,可是對於大n,它就不算快了,更快的一種排序算法是歸併排序。

 

8 引入歸併排序

8.1 歸併排序步驟

S1:若是n=1,那麼結束;

S2:不然,遞歸地排序A[1,…[n/2]]和A[[n/2]+1,…n]

S3: 將2個已經排序好的表合併在一塊兒(’Merge’)

8.2 歸併子程序 

這裏用到了一個歸併子程序,這也是這個算法的關鍵。

假設2張已經按照從小到大排序好的表,如何合併?

由於最小的元素必定是2張表中首個元素之一。因此每次對比2張表中最小元素便可。

舉例:

1 7 11 13 15 19

3 4 9 18 20 22

首先比較1,3,取1,而後第一個表劃掉1

而後比較7和3,取3,而後第二個表劃掉3

而後比較7和9,取7,而後第一個表劃掉7

以此類推

這個過程運行時間是Θ(n),由於每一個元素用了一次對比,是常數時間,而後作了n次,因此是Θ(n),也就是線性時間。

 

9 歸併排序運行時間分析(遞歸樹方法)

因此T(n)={Θ(1) if n=1;

                   2T(n/2)+Θ(n)(if n>1)(注意:Θ(n)+Θ(1)=Θ(n)}

已經知道遞歸式子了,那麼運行時間如何求解?

能夠用遞歸樹的方法求解運行時間,具體的在Lecture2 會講到,咱們只要考慮n>1的狀況便可

此時T(n)能夠表示成爲2*T(n/2)+C*n

構造遞歸樹方法:

1 先把遞歸式子的左半部分寫出來

 

注意:式子右邊樹上的葉子加起來正好就是T(n),好比第一顆樹,T(n)=Cn+T(n/2)*2

高度(層數)約爲log(n)(視頻上寫着log(n),我的以爲應該是表示log2(n),後面也直接用log(n)表示)

這裏強調「約」,是由於n不必定是2的整數冪,可是接近。

假設n是2的整數冪,那麼講到Θ(1),正好有log(n)步,n->n/2->n/4->…1,其實是log(n)的常數倍。

最底層的葉子節點數目是n

T(n)表達式?

爲了獲得T(n),考慮把全部樹上葉子加起來是多少。

除了最後一層,每一層的綜合都是C*n,最後一層不必定是C*n,由於邊界狀況可能存在別的值,記爲Θ(n)

因此總數T(n)=Cn*log(n)+Θ(n)(第一項比第二項高)=Θ(n*logn)

考慮漸近狀況下,Θ(n*logn)比Θ(n2)要快,因此歸併排序在一個充分大的輸入規模n下將優於插入排序。

 

10待解決疑問:

1好比遞歸樹原理,有待下一講一些理論

2 爲何在漸近狀況下,Θ(n*logn)<<Θ(n2)

相關文章
相關標籤/搜索