MIT算法导论01-课程简介及算法分析
课程名:Introduction to Algorithms
课程编号:6.046J/18.410J
授课教师:Prof. Charles Leiserson Prof.Erik Demame
预备课程
- 6.042,计算科学的数学基础
- 6.001,Structure and Interpretation of Computer Programs《计算机程序的构造与解释》
- 离散数学
- 概论论
Analysis of Algorithms 算法分析
目的: 掌握分析算法的实用技巧,设计算法时知道哪种方式更有效。算法是关于计算机性能和资源利用的研究。
Q1: 程序设计时,有哪些东西是什么比性能更重要的?
正确性、可维护性、开发成本、稳定性、功能性、模块化、安全性、用户友好性等。
Q2: 这么多比性能更重要的东西,为何还要学习算法?
- 性能决定程序可用还是不可用。算法总是处于解决问题的最前沿。算法能够将不可行变成可行。
- 算法是一种描述程序行为的语言,已经被所有的实践者所采用的理论语言。它是一种让程序最为简洁的思考方式。
排序问题
问题描述: 输入数组 ( a 1 , a 2 , a 3 , ⋯ a n ) (a_1,a_2, a_3,\cdots a_n) (a1,a2,a3,⋯an), 输出排好序的数组 a 1 ′ , a 2 ′ , a 3 ′ , ⋯ , a n ′ a_1^{'},a_2^{'},a_3^{'},\cdots,a_n^{'} a1′,a2′,a3′,⋯,an′,使得 a 1 ′ ≤ a 2 ′ ≤ a 3 ′ ≤ ⋯ ≤ a n ′ a_1^{'}\le a_2^{'}\le a_3^{'}\le \cdots\le a_n^{'} a1′≤a2′≤a3′≤⋯≤an′
插入排序(Insertion sort)
Insertion-Sort(An)//Sorts A[1. .n]
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
说明: 课程使用伪代码(pseudocode)描述程序。语法:使用缩进,相当于大括号。
Eg:
8 2 4 9 3 6
2 8 4 9 3 6
2 4 8 9 3 6
2 4 8 9 3 6
2 3 4 8 9 6
2 3 4 6 8 9
Running time 运行时间
- Depends on input(eg. already sorted)
- Depends on input size(6 elements vs 6*10^9)
- parameterize in input size;
- Want upper bonds on the running time.
- a guarantee to the user.
Kinds of analysis 分析方式
-
Worst case(usually).
T(n)= max time on any input of size n; -
Average case(sometimes).
T(n)= expected time over all inputs of size n; (weighted average)
Need assumption of statistical distribution(one of the most common assumptions is uniform distribution). -
Best case (bogus) ,useless, cheat一般不用最好情况分析,因为具有欺骗性,没有太多实际意义
What is insertion sorts worst-case time? 插入排序最坏情况下的运行时间
Depends on computer
- relative speed (on same machine)
- absolute speed (on different machine)
BIG IDEA asymptotic analysis 渐近分析
- Ignore machine dependent constants
- Look at growth of T(n) as n → ∞ n \rightarrow \infty n→∞
Asymptotic notation 渐近表示法
θ
\theta
θ -notation: Drop low order terms and ignore leading constants.
Eg:
3
n
3
+
90
n
2
−
5
n
+
6046
=
θ
(
n
3
)
3n^3+90n^2-5n+6046=\theta (n^3)
3n3+90n2−5n+6046=θ(n3)
related O-notation and
Ω
\Omega
Ω -notation
as n → ∞ n \rightarrow \infty n→∞ , θ ( n 2 ) \theta (n^2) θ(n2) algorithm always beats a θ ( n 3 ) \theta (n^3) θ(n3) algorithm
asymptotic notation satisfies our issue of being able to compare both relative and absolute speed. 渐近表述能一举满足相对速度和绝对速度的双重比较要求。
但有时“低效算法”也有其意义,因为有时虽然有种算法在n趋于无穷大时比另一种要好,但临界值太大,一般不会有那么大的输入规模时,可以考虑使用“低效”算法。
需要在数学理解和工程直觉之间取得平衡才能写出好用的程序
如果你想成为一个编程高手,只要两年中每天坚持编程,如果你想成为一名世界级大牛,你既可以十年如一日每天坚持编程,也可以两年中每天编程,然后上一门算法可。
插入排序分析
- Worst- case: input reverse sorted
T ( n ) = ∑ j = 2 n Θ ( j ) = Θ ( n 2 ) T(n)=\sum\limits_{j=2}^n \Theta(j)=\Theta(n^2) T(n)=j=2∑nΘ(j)=Θ(n2)
算术级数:Arithmetic series
notes: Θ \Theta Θ是一种弱符号,不需要搞清楚它具体代表何种运算,与其说是一个运算符号,不如说他是个描述符号。 - 插入排序快吗?
- n较小时比较快
- 但n较大时不快
Merge sort 归并排序
if n=1, done
recursively sort
A[1,..., n/2] and A[n/2+1 to n]
Merge 2 sorted lists
T ( n ) T(n) T(n) | Merge sort A[1…n] |
---|---|
Θ ( 1 ) \Theta(1) Θ(1) | 1. if n = 1 n=1 n=1, done |
2 T ( n / 2 ) 2T(n/2) 2T(n/2) | 2. recursively sort A [ 1 , ⋯ , ⌈ n / 2 ⌉ ] A[1,\cdots,\lceil n/2\rceil] A[1,⋯,⌈n/2⌉] and A [ ⌈ n / 2 ⌉ + 1 , ⋯ , n ] A[\lceil n/2\rceil +1,\cdots,n] A[⌈n/2⌉+1,⋯,n] |
Θ ( n ) \Theta(n) Θ(n) | 3. Merge 2 sorted lists |
Key subroutine: Merge
观察两个有序表头部元素哪个小。
Time=
Θ
(
n
)
\Theta(n)
Θ(n) on n total elements
Recurrence 递归
T ( n ) = { Θ ( 1 ) i f n = 1 ( u s u a l y o m i t ) 2 T ( n / 2 ) + Θ ( n ) i f n > 1 T(n)=\left \{ \begin{array}{ll}\Theta(1) & if \quad n=1\quad (usualy\quad omit)\\2T(n/2)+ \Theta(n) &if \quad n>1\end{array}\right. T(n)={Θ(1)2T(n/2)+Θ(n)ifn=1(usualyomit)ifn>1
Recursion tree 递归树
T
(
n
)
=
2
T
(
n
/
2
)
+
c
n
T(n)=2T(n/2)+cn
T(n)=2T(n/2)+cn(由于
Θ
(
n
)
\Theta(n)
Θ(n)是线性的,故可以显式地写成
c
n
,
c
>
0
cn,c>0
cn,c>0)
递归树高度: h = l g n h=lgn h=lgn,每级使用的时间为 c n cn cn,叶节点数量为 n n n,,所有叶节点用时 Θ ( n ) \Theta(n) Θ(n),总用时 T ( n ) = c n ∗ l g n + Θ ( n ) = Θ ( n l g n ) T(n)=cn*lgn+\Theta(n)=\Theta(nlgn) T(n)=cn∗lgn+Θ(n)=Θ(nlgn)
在 n > 30 n>30 n>30时,归并排序就比插入排序快了。