麻省理工公开课《算法导论》学习笔记:第一讲

主题:简介课程,渐近概念的大局观,插入排序和归并排序,递归式函数时间分析(递归树方法)算法

教材:《算法导论》安全

收获:很感动地看到算法分析那个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)

相关文章
相关标签/搜索