主题:简介课程,渐近概念的大局观,插入排序和归并排序,递归式函数时间分析(递归树方法)算法
教材:《算法导论》安全
收获:很感动地看到算法分析那个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)