算法导论中文版
- 格式:pdf
- 大小:411.47 KB
- 文档页数:37
《算法导论(原书第3版)》读后感在去年初夏的某个夜晚,当我看完“蒲慕明所长在中科院神经所2010 年会上的讲话”后,不禁又想起了这本令我印象深刻的书籍。
去年五月,我大致通读了《算法导论》,但不敢说自己完全理解了其中的内容。
虽然我按照提示完成了部分习题,但后来由于搬家等事务繁忙,未能深入研读。
在我看来,这本书更像是一本编写得像教材的文献综述。
此外,我还意识到,这本书至少有40%的精华都蕴含在课后习题中。
关于这本书的评价和总结已经数不胜数,我只想谈一谈自己的一些个人感悟。
尽管算法的理论常常涉及计算复杂性理论,但算法归根结底是一门实验科学。
一个精妙设计的算法在很大程度上依赖于问题本身的固有性质。
总体而言,提出一个有效的算法需要深入研究以下三个方面(它们是相互关联、循序渐进的): 1. 问题本身的性质和特点:例如,分治算法基于问题的子问题之间存在较弱的约束,而贪心求解算法则基于局部最优就是全局最优的特点。
2. 算法的性能受到哪些因素的影响,以及这些因素如何影响算法,其机制是什么:例如,动态规划的效率与初始随机点的选择方式有关,可满足性问题的解搜索耗时与节点的策略设定有关。
3. 在前面两个部分的基础上提出框架或进行改进,构建一个高效的算法:例如,快速排序是在归并排序的基础上进行改进的,计算代数中的 F5 算法是在 Buchberger 算法的基础上进行改进的,它们都是基于对前两个部分更深入的研究。
我要指出的是,以上三个部分需要大量的实验(验证/试错)来贯彻执行,这就是那“天才的百分之九十九的汗水”。
然而,“秘诀在于使用简单、步骤少、并行且可反复修改的科研方案”。
我们可以看到,神经科学未来的发展趋势所关注的是,最大的问题不是观察什么现象,而是探索这些现象在不同层面上的联系。
例如,我们研究神经系统,从基因到分子细胞,到环路,再到系统,最后到行为,每个层面都有其自身的问题。
现在,最大的问题是,往往一个层面的问题与另一个层面的问题存在相关性,但我们不清楚这种相关性是如何产生的。
补充递归和分治策略•通过例子理解递归的概念;•掌握设计有效算法的分治策略;•通过下面的范例学习分治策略设计技巧:过的范例学分策略技¾Merge sort¾Multiplication of two numbers¾Multiplication of two matrices¾Finding Minimum and Maximumj y p¾Majority problem (多数问题)算法总体思想对这k个子问题分别求解。
如果子问题的规模仍然不够z 将要求解的较大规模的问题分割成k个更小规模的子问小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。
题。
nT(n)=T(n/2)T(n/2)T(n/2)T(n/2)算法总体思想将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
nT(n)=n/2n/2n/2n/2T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4) T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)算法总体思想将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是将个难以直接解决的大问题n T(n)=分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之分而治之。
n/2n/2n/2n/2T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4递归的概念直接或间接地调用自身的算法称为z递归算法。
多线程算法(完整版)——算法导论第3版新增第27章Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein邓辉译原文:/sites/products/documentation/cilk/book_chapter.pdf本书中的主要算法都是顺序算法,适合于运行在每次只能执行一条指令的单处理器计算机上。
在本章中,我们要把算法模型转向并行算法,它们可以运行在能够同时执行多条指令的多处理器计算机中。
我们将着重探索优雅的动态多线程算法模型,该模型既有助于算法的设计和分析,同时也易于进行高效的实现。
并行计算机(就是具有多个处理单元的计算机)已经变得越来越常见,其在价格和性能方面差距甚大。
相对比较便宜的有片上多处理器桌面电脑和笔记本电脑,其中包含着一个多核集成芯片,容纳着多个处理“核”,每个核都是功能齐全的处理器,可以访问一个公共内存。
价格和性能都处于中间的是由多个独立计算机(通常都只是些 PC 级的电脑)组成的集群,通过专用的网络连接在一起。
价格最高的是超级计算机,它们常常采用定制的架构和网络以提供最高的性能(每秒执行的指令数)。
多处理器计算机已经以各种形态存在数十年了。
计算社团早在计算机科学形成的初期就选定采用随机存取的机器模型来进行串行计算,但是对于并行计算来说,却没有一个公认的模型。
这主要是因为供应商无法在并行计算机的架构模型上达成一致。
比如,有些并行计算机采用共享内存,其中每个处理器都可以直接访问内存的任何位置。
而有些并行计算机则使用分布式内存,每个处理器的内存都是私有的,要想去访问其他处理器的内存,必须得向其他处理器发送显式的消息。
不过,随着多核技术的出现,新的笔记本和桌面电脑目前都成为共享内存的并行计算机,趋势似乎倒向了共享内存多处理这边。
虽然一切还是得由时间来证明,不过我们在章中仍将采用共享内存的方法。
对于片上多处理器和其他共享内存并行计算机来说,使用静态线程是一种常见的编程方法,该方法是一种共享内存“虚拟处理器”或者线程的软件抽象。
补充递归和分治策略•通过例子理解递归的概念;•掌握设计有效算法的分治策略;•通过下面的范例学习分治策略设计技巧:过的范例学分策略技¾Merge sort¾Multiplication of two numbers¾Multiplication of two matrices¾Finding Minimum and Maximumj y p¾Majority problem (多数问题)算法总体思想对这k个子问题分别求解。
如果子问题的规模仍然不够z 将要求解的较大规模的问题分割成k个更小规模的子问小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。
题。
nT(n)=T(n/2)T(n/2)T(n/2)T(n/2)算法总体思想将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
nT(n)=n/2n/2n/2n/2T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4) T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)T(/4)算法总体思想将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是将个难以直接解决的大问题n T(n)=分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之分而治之。
n/2n/2n/2n/2T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4)T(n/4递归的概念直接或间接地调用自身的算法称为z递归算法。
用函数自身给出定义的函数称为递归函数。
z由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。
在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。
这自然导致递归过程的产生。
z分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
下面来看几个实例。
递归的例子例1 阶乘函数阶乘函数可递归地定义为:边界条件01!=⎧=n n 0)!1(>⎩⎨−n n n 递归方程边界条件与递归方程是递归函数的二个要素,递归函数只有具备了这两个要素,才能在有限次计算后得出结果。
递归的例子例2 排列问题设计一个递归算法生成n个元素{r 1,r 2,…,r n }的全排列。
设R={r …1,r 2,,r n }是要进行排列的n个元素,R i =R-{r i }。
集合X中元素的全排列记为perm(X)。
(r i )perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。
R的全排列可归纳定义如下:当n=1时,perm(R)=(r),其中r是集合R中唯一的元素;当n>1时,perm(R)由(r 1)perm(R 1),(r 2)perm(R 2),…,(r )perm(R )构成。
n n 7递归的例子例3 整数划分问题将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。
正整数n的这种表示称为正整数n的划分。
求正整数n的不同划分个数。
例如正整数6有如下11种不同的划分:6;5+1;4+2,4+1+1;3+3,3+2+1,3+1+1+1;2+2+2,2+2+1+1,2+1+1+1+1;1+1+1+1+1+1。
递归的例子例3 整数划分问题前面的几个例子中,问题本身都具有比较明显的递归关系,因而容易用递归函数直接求解。
在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加一个自变量:将最大加数n 1不大于m的划分个数记作q(n,m)。
可以建立q(n,m)的如下递归关系。
(1) q(n,1)=1,n ≥1;(3) q(n,n)=1+q(n,n-1);(2)q(n,m)=q(n,n),m 当最大加数n 1不大于1时,任何正整数n只有一种划分形式,即48476Λn n 111+++=(4)q(n,m)=q(n,m-1)+q(n-m,m),n>m>1;正整数n的划分由n 1=n的划分和n 1≤n-1的划分组成。
(2) q(n,m)=q(n,n),m ≥n;最大加数n 1实际上不能大于n。
因此,q(1,m)=1。
(4) q(n,m)=q(n,m-1)+q(n-m,m),n>m>1;正整数n的最大加数n 1不大于m的划分由n 1=m的划分和≤n-1的划分组成。
9n 1≤n-1 的划分组成。
递归的例子例3 整数划分问题前面的几个例子中,问题本身都具有比较明显的递归关系,因而容易用递归函数直接求解。
在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加一个自变量:将最大加数n 1不大于m的划分个数记作q(n,m)。
可以建立q(n,m)的如下递归关系。
⎪⎧==1,11n m n ⎪⎪⎨=<−+=)1,(1),(),(m n m n n q n n q m n q ⎪⎩>>−+−1),()1,(m n m m n q m n q 正整数n的划分数p(n)=q(n,n)。
递归小结优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。
递归小结解决方法:在递归算法中消除递归调用,使其转化为非递归算法。
1、采用一个用户定义的栈来模拟系统的递归调用工作栈。
该方法通用性强,但本质上还是递归,只不过人工做了本来由编译器做的事情,优化效果不明显。
2、用递推来实现递归函数。
3、通过变换能将一些递归转化为尾递归,从而迭代求出结果。
后两种方法在时空复杂度上均有较大改善,但其适用范围有限。
分治法的适用条件分治法所能解决的问题一般具有以下几个特征:分治法所能解决的问题般具有以下几个特征:z 该问题的规模缩小到一定的程度就可以容易地解决;z 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质z 利用该问题分解出的子问题的解可以合并为该问题的解;z 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
因为问题的计算复杂性一般是随着问题规模的增加这条特征涉及到分治法的效率,如果各子问题是不而增加,因此大部分问题满足这个特征。
这条特征是应用分治法的前提,它也是大多数问题可以满足的,此特征反映了递归思想的应用能否利用分治法完全取决于问题是否具有这条特征,如果具备了前两条特征,而不具备第三条特征,则可以考虑贪心算法或动态规划。
独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然也可用分治法,但一般用动态规划较好。
分治法的基本步骤:分治法的基本步骤divide-and-conquer(P){if( | P | <= n0) adhoc(P); //解决小规模的问题divide P into smaller subinstances P1,P2,...,Pk;//分解问题P into smaller subinstances P1P2Pkfor(i=1,i<=k,i++)y d v de d co que();//递归的解各子问题yi=divide-and-conquer(Pi); //return merge(y1,...,yk); //将各子问题的解合并为原问题的解}人们从大量实践中发现,在用分治法设计算法时,最好使子问题的规模大致相同。
即将一个问题分成大小相等的k个子问题的处理方法是行之有效的。
这种使子问题规模大致相等的做法是出自一种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。
分治法的复杂性分析一个分治法将规模为n的问题分成k个规模为n/m的子问题去解。
设分解阀值n0=1,且adhoc解规模为1的问题耗费1个单位时间。
再设将原问题分解为k个子问题以及用merge将k个子问题的解合并为原问题的解需用f(n)个单位时间。
用T(n)表示该分治法解规模为|P|=n的问题所需的计算时间,则有:=⎧11)()/()1()(>⎩⎨+=n n n f m n kT O n T −1logn 通过迭代法求得方程的解:∑=+=g 0log )/()(mj jjkm m n f knn T 注意:递归方程及其解只给出n 等于m 的方幂时T(n)的值,但是如果认为T(n)足够平滑,那么由n 等于m 的方幂时T(n)的值可以估计T(n)的增长速度。
通常假定T(n)是单调上升的,从而当m i ≤n<m i+1时,T(m i )≤T(n)<T(m i+1)。
Examples:分治法例子pz Merge sortMultiplication of two numbers z Multiplication of two numbers z Multiplication of two matrices z Finding Minimum and Maximum z Majority problem (多数问题j y p ()z 循环赛日程表1. 整数相乘问题。
分治法的例子X 和Y 是两个n 位的十进制整数,分别表示为X=x n-1x n-2...x 0, Y=y n-1y n-2...y 0,其中0 ≤ x i , y ≤ 9 (i,j j=0,1,…n-1) ,设计一个算法求X ×Y ,并分析其计算复杂度。
说明:算法中“基本操作”约定为两个个位整数以及两个整数相加相乘x i ×y j ,以及两个整数相加。
2. 矩阵相乘问题。
阶实方阵表示为111...n a a ⎛⎞⎜⎟111...n b b ⎛⎞⎜⎟A 和B 是两个n 阶实方阵,表示为,设计个算法求并分析计算复杂度1...........n nn a a =⎜⎟⎜⎟⎝⎠A 1...........n nn b b =⎜⎟⎜⎟⎝⎠B 设计一个算法求A ×B ,并分析计算复杂度。
说明:算法中“基本操作”约定为两个实数相乘,或两个实数相加个实数相加。
Exam1M lti li ti f t b two n -digit numbers X and Y, Complexity(X ×Y) = ?Exam1 Multiplication of two numbers (大整数的乘法)zNaive (原始的) pencil-and-paper algorithm31415962×271828182513276963141596212×2325132769662831924251327696634314159622199117342276Complexity analysis: n 2multiplications and at most 62831924853974377340916p y y pn 2-1additions (加法). So, T (n )=O (n 2).Exam1M lti li ti f t bExam1 Multiplication of two numbers(大整数的乘法)two n-digit numbers X and Y, Complexity(X ×Y) = ?z Divide and Conquer algorithmLet X = a bY = c dwhere a, b, c and d are n/2 digit numbers, e.g.1364=13×102+64.Let m= n/2. ThenXY = (10m a+b)(10m c+d)=102m ac+10m(bc+ad)+bdExam1M lti li ti f t btwo n-digit numbers X and Y, Complexity(X ×Y) = ? Exam1 Multiplication of two numbers(大整数的乘法)z Divide and Conquer algorithmLet X = a b,Y = c dthen XY = (10m a+b)(10m c+d) = 102m ac+10m(bc+ad)+bd Multiply(X; Y; n):if1if n= 1 return X×Y else Complexity analysis: T(1)=1,m= ⎡n/2⎤a= ⎣X/10m⎦; b=X mod 10m c= ⎣Y/10m⎦; d=Y mod 10m =Multiply(;;T(n)=4T(⎡n/2⎤)+O(n). Applying Master Theorem, he= Multiply(a; c; m) f= Multiply(b; d; m) g= Multiply(b; c; m) =Multiply(;;we have T(n)=O(n2).h Multiply(a; d; m) return 102m e+ 10m(g+ h) + fExam1M lti li ti f t b two n -digit numbers X and Y, Complexity(X ×Y) = ?Exam1 Multiplication of two numbers (大整数的乘法)z Divide and Conquer (Karatsuba’s algorithm )Let X = a b ,Y = c d XY =(10)=10then XY = (10m a +b )(10m c +d ) = 102m ac +10m (bc +ad )+bd Note that bc + ad = ac + bd −(a −b )(c −d ). So, we haveF tM lti l (X Y )FastMultiply(X; Y; n ):if n = 1return X ×Y Complexity analysis:(1)1elsem = ⎡n /2⎤a = ⎣X/10m ⎦;b =X mod 10m =m ;=Y mod 10m T (1)=1, T (n )=3T (⎡n /2⎤)+O (n ).Applying Master Theorem,c ⎣Y/10⎦; d Y mod 10e = FastMultiply(a; c; m )f = FastMultiply(b; d; m )g =−b;c −d;m Applying Master Theorem, we havelog 31.59g FastMultiply(a b; c d; m )return 102m e + 10m (e + f −g )+ f2g ()()()T n O nO n==Exam1M lti li ti f t bExam1 Multiplication of two numbers(大整数的乘法)请设计一个有效的算法,可以进行两个n位大整数的乘法运算 小学的方法:O(n2) 8效率太低分治法: O(n1.59) 9较大的改进:O(n)更快的方法??¾如果将大整数分成更多段,用更复杂的方式把它们组合起来,将有可能得到更优的算法。