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


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

教材:《算法導論》

收獲:很感動地看到算法分析那個log(n)是為什么出現了,更深層還要聽第二講,若不是因為要准備SAS,恨不得馬上看。

內容:

1 何為算法分析?

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

 

2 比性能更加重要的因素都有哪些?

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

 

3 那為何還學習算法和性能?

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

學習算法的原因:

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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM