ImageVerifierCode 换一换
格式:DOCX , 页数:43 ,大小:77.96KB ,
资源ID:5063543      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-5063543.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(算法合集之数据结构的在程序设计中的应用Word格式.docx)为本站会员(b****1)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

算法合集之数据结构的在程序设计中的应用Word格式.docx

1、首先,我们这里所讲的“信息”,指的是元素与元素之间的关系。对于待处理的信息,大致可分为“可直接使用”和“不可直接使用”两类。对于“可直接使用”的信息,我们使用时十分方便,只需直接拿来就可以了。而对于“不可直接使用”的这一类,我们也可以通过某些间接的方式,使之成为可以使用的信息,但其中转化的过程显然是比较浪费时间的。由此可见,我们所需要的是尽量多的“可直接使用”的信息。这样的信息越多,算法的效率就会越高。对于不同的逻辑结构,其包含的信息是不同的,算法对信息的利用也会出现不同的复杂程度。因此,要使算法能够充分利用“可直接使用”的信息,而避免算法在信息由“不可直接使用”向“可直接使用”的转化过程中浪

2、费过多的时间,我们必然需要采用一种合理的逻辑结构,使其包含更多“可直接使用”的信息。问题一 IOI99的隐藏的码字。问题描述问题中给出了一些码字和一个文本,要求编程找出文本中包含这些码字的所有项目,并将找出的项目组成一个最优的“答案”,使得答案中各项目所包含的码字长度总和最大。每一个项目包括一个码字,以及该码字在文本中的一个覆盖序列(如abcadc就是码字abac的一个覆盖序列),并且覆盖序列的长度不超过1000。同时,“答案”要求其中每个项目的覆盖序列互相没有重叠。问题分析对于此题,一种较容易得出的基本算法是:对覆盖序列在文本中的终止位置进行循环,再判断包含了哪些码字,找出所有项目,并最后使

3、用动态规划的方法将项目组成最优的“答案”。算法的其它方面我们暂且不做考虑,而先对问题所采用的逻辑结构进行选择。如果我们采用线性的逻辑结构(如循环队列),那么我们在判断是否包含某个码字t时,所用的方法为:初始时用指针p指向终止位置,接着通过p的不断前移,依次找出码字t从尾到头的各个字母。例如码字为“ABDCAB”,而文本图1-1,终止位置为最右边的箭头符号,每个箭头代表依次找到的码字的各个字母。 指针p的移动方向 A B D C A BCDAB 图1-1由于题目规定码字的覆盖序列长度不超过1000,所以进行这样的一次是否包含的判断,其复杂度为O(1000)。由于码字t中相邻两字母在文本中的位置,

4、并非只有相邻(如图1-1中的D和C)这一种关系,中间还可能间隔了许多的字母(如图1-1中C和A就间隔了2个字母),而线性结构中拥有的信息,仅仅只存在于相邻的两元素之间。通过这样简单的信息来寻找码字的某一个字母,其效率显然不高。如果我们建立一个有向图,其中顶点i(即文本的第i位)用52条弧分别连接a.z,A.Z这52个字母在i位以前最后出现的位置(如图1-2的连接方式),我们要寻找码字中某个字母的前一个字母,就可以直接利用已连接的边,而不需用枚举的方法。我们也可以把问题看为:从有向图的一个顶点出发,寻找一条长度为length(t)-1的路径,并且路径中经过的顶点,按照码字t中的字母有序。 图1-

5、2通过计算,用图进行记录在空间上完全可以承受(记录1000个点52条弧4字节的长整型=200k左右)。在时间上,由于可以充分利用第i位和第i+1位弧的连接方式变化不大这一点(如图1-2所示,第i位和第i+1位只有一条弧的指向发生了变化,即第i+1位将其中一条弧指向了第i位),所以要对图中的弧进行记录,只需对弧的指向进行整体赋值,并改变其中的某一条弧即可。因此,我们通过采用图的逻辑结构,使得寻找字母的效率大大提高,其判断的复杂度为O(length(t),最坏为O(100),比原来方法的判断效率提高了10倍。 (附程序codes.pas)对于这个例子,虽然用线性的数据结构也可以解决,但由于判断的特

6、殊性,每次需要的信息并不能从相邻的元素中找到,而线性结构中只有相邻元素之间存在关系的这一点,就成为了一个很明显的缺点。因此,问题一线性结构中的信息,就属于“不可直接使用”的信息。相对而言,图的结构就正好满足了我们的需要,将所有可能产生关系的点都用弧连接起来,使我们可以利用弧的关系,高效地进行判断寻找的过程。虽然图的结构更加复杂,但却将“不可直接使用”的信息,转化成为了“可直接使用”的信息,算法效率的提高,自然在情理之中。二、不记录“无用”信息。从问题一中我们看到,由于图结构的信息量大,所以其中的信息基本上都是“可用”的。但是,这并不表示我们就一定要使用图的结构。在某些情况下,图结构中的“可用”

7、信息,是有些多余的。信息都“可用”自然是好事,但倘若其中“无用”(不需要)的信息太多,就只会增加我们思考分析和处理问题时的复杂程度,反而不利于我们解决问题了。问题二 湖南省1997年组队赛的乘船问题 有N个人需要乘船,而每船最多只能载两人,且必须同名或同姓。求最少需要多少条船。 看到这道题,很多人都会想到图的数据结构:将N个人看作无向图的N个点,凡同名或同姓的人之间都连上边。要满足用船最少的条件,就是需要尽量多的两人共乘一条船,表现在图中就是要用最少的边完成对所有顶点的覆盖。这就正好对应了图论的典型问题:求最小边的覆盖。所用的算法为“求任意图最大匹配”的算法。使用“求任意图最大匹配”的算法比较

8、复杂(要用到扩展交错树,对花的收缩等等),效率也不是很高。因此,我们必须寻找一个更简单高效的方法。 首先,由于图中任两个连通分量都是相对独立的,也就是说任一条匹配边的两顶点,都只属于同一个连通分量。因此,我们可以对每个连通分量分别进行处理,而不会影响最终的结果。同时,我们还可以对需要船只s的下限进行估计:对于一个包含Pi个顶点的连通分量,其最小覆盖边数显然为Pi/2。若图中共有L个连通分量,则s=Pi/2(1=i=L)。 然后,我们通过多次尝试,可得出一个猜想: 实际需要的覆盖边数完全等于我们求出的下限Pi/2(10)表示lcp,i-1的左儿子,显然lcp,i与p是同姓的。 假设存在某个点q,

9、满足qs且qT。由于s是有限集合,因而必然存在某个lcp,k无左儿子。则我们可以令lcp,k+1=q,所以qT,与假设qT相矛盾。所以假设不成立,原命题得证。由引理2.1的证明方法,我们同理可证引理2.2。【引理2.2】若二叉树T中包含了某个结点p,那么连通分量中所有与p同名的点一定都在T中。 有了上面的两个引理,我们就不难得出下面的定理了。【定理一】 以连通分量中的任一点p作为根结点的二叉树,必然能够包含连通分量中的所有顶点。 由引理2.1和引理2.2,所有与p同姓或同名的点都一定在二叉树中,即连通分量中所有与p有边相连的点都在二叉树中。由连通分量中任两点间都存在路径的特性,该连通分量中的所

10、有点都在二叉树中。 在证明二叉树中包含了连通分量的所有顶点后,我们接着就需要证明我们的猜想,也就是下面的定理:【定理二】包含m个结点的二叉树Tm,只需要船的数量为boatm=m/2(mN)。(i)当m=1,m=2,m=3时命题显然成立。 图2-2-1 图2-2-2 图2-2-3(ii)假设当m3)时命题成立,那么当m=k时,我们首先从树中找到一个层次最深的结点,并假设这个结点的父亲为p。那么,此时有且只有以下三种情况(结点中带有阴影的是p结点):(1)如图2-2-1,p只有一个儿子。此时删去p和p唯一的儿子,Tk就成为了Tk-2,则boatk=boatk-2+1=(k-2)/2+1=k/2。(

11、2)如图2-2-2,p有两个儿子,并且p是其父亲的左儿子。此时可删去p和p的右儿子,并可将p的左儿子放到p的位置上。同样地,Tk成为了Tk-2,boatk=boatk-2+1=k/2。(3)如图2-2-3,p有两个儿子,并且p是其父亲的右儿子。此时可删去p和p的左儿子,并可将p的右儿子放到p的位置上。情况与(2)十分相似,易得此时得boatk=boatk-2+1=k/2。综合(1)、(2)、(3),当m=k时,boatk=k/2。最后,综合(i)、(ii),对于一切mN,boatm=m/2。 由上述证明,我们将问题中数据的图结构转化为树结构后,可以得出求一棵二叉树的乘船方案的算法: proc

12、try(father:integer;var root:var rest:byte); 输出root为树根的子树的乘船方案,father=0表示root是其父亲的左儿子,father=1表示root是其父亲的右儿子,rest表示输出子树的乘船方案后,是否还剩下一个根结点未乘船 beginvisitroot:=true; 标记root已访问找到一个与root同姓且未访问的结点j; if jn+1 then try(0,j,lrest);找到一个与root同姓且未访问的结点k;if kn+1 then try(1,k,rrest);if (lrest=1) xor (rrest=1) then b

13、egin 判断root是否只有一个儿子,情况一 if lrest=1 then print(lrest,root) else print(rrest,root);rest:=0;endelse if (lrest=1) and (rrest=1) then begin 判断root是否有两个儿子 if father=0 then beginprint(rrest,root);root:=j; 情况二 end else begin print(lrest,root);=k; 情况三 end; rest:=1; endelse rest:end; 这只是输出一棵二叉树的乘船方案的算法,要输出所有人

14、的乘船方案,我们还需再加一层循环,用于寻找各棵二叉树的根结点,但由于每个点都只会访问一次,寻找其左右儿子各需进行一次循环,所以算法的时间复杂度为O(n2)。(附程序boat.pas) 最后,我们对两种结构得出不同时间复杂度算法的原因进行分析。其中最关键的一点就是因为二叉树虽然结构相对较简单,但已经包含了几乎全部都“有用”的信息。由我们寻找乘船方案的算法可知,二叉树中的所有边不仅都发挥了作用,而且没有重复的使用,可见信息的利用率也是相当之高的。 既然采用树结构已经足够,图结构中的一些信息就显然就成为了“无用”的信息。这些多余的“无用”信息,使我们在分析问题时难于发现规律,也很难找到高效的算法进行

15、解决。这正如迷宫中的墙一样,越多越难走。“无用”的信息,只会干扰问题的规律性,使我们更难找出解决问题的方法。小结 我们对数据的逻辑结构进行选择,是构造数学模型一大关键,而算法又是用来解决数学模型的。要使算法效率高,首先必须选好数据的逻辑结构。上面已经提出了选择逻辑结构的两个条件(思考方向),总之目的是提高信息的利用效果。利用“可直接使用”的信息,由于中间不需其它操作,利用的效率自然很高;不不记录“无用”的信息,就会使我们更加专心地研究分析“有用”的信息,对信息的使用也必然会更加优化。 总之,在解决问题的过程中,选择合理的逻辑结构是相当重要的环节。三、选择合理的存储结构数据的存储结构,分为顺序存

16、储结构和链式存储结构。顺序存储结构的特点是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系;链式存储结构则是借助指示元素存储地址的指针表示数据元素之间的逻辑关系。因为两种存储结构的不同,导致这两种存储结构在具体使用时也分别存在着优点和缺点。 这里有一个较简单的例子:我们需要记录一个nn的矩阵,矩阵中包含的非0元素为m个。 此时,我们若采用顺序存储结构,就会使用一个nn的二维数组,将所有数据元素全部记录下来;若采用链式存储结构,则需要使用一个包含m个结点的链表,记录所有非0的m个数据元素。由这样两种不同的记录方式,我们可以通过对数据的不同操作来分析它们的优点和缺点。1随机访问矩阵中任意元

17、素。由于顺序结构在物理位置上是相邻的,所以可以很容易地获得任意元素的存储地址,其复杂度为O(1);对于链式结构,由于不具备物理位置相邻的特点,所以首先必须对整个链表进行一次遍历,寻找需进行访问的元素的存储地址,其复杂度为O(m)。此时使用顺序结构显然效率更高。2对所有数据进行遍历。两种存储结构对于这种操作的复杂度是显而易见的,顺序结构的复杂度为O(n2),链式结构为O(m)。由于在一般情况下m要远小于n2,所以此时链式结构的效率要高上许多。除上述两种操作外,对于其它的操作,这两种结构都不存在很明显的优点和缺点,如对链表进行删除或插入操作,在顺序结构中可表示为改变相应位置的数据元素。 既然两种存

18、储结构对于不同的操作,其效率存在较大的差异,那么我们在确定存储结构时,必须仔细分析算法中操作的需要,合理地选择一种能够“扬长避短”的存储结构。一、合理采用顺序存储结构。我们在平常做题时,大多都是使用顺序存储结构对数据进行存储。究其原因,一方面是出于顺序结构操作方便的考虑,另一方面是在程序实现的过程中,使用顺序结构相对于链式结构更便于对程序进行调试和查找错误。因此,大多数人习惯上认为,能够使用顺序结构进行存储的问题,最“好”采用顺序存储结构。其实,这个所谓的“好”只是一个相对的标准,是建立在以下两个前提条件之下的:1链式结构存储的结点与顺序结构存储的结点数目相差不大。这种情况下,由于存储的结点数

19、目比较接近,使用链式结构完全不能体现出记录结点少的优点,并且可能会由于指针操作较慢而降低算法的效率。更有甚者,由于指针自身占用的空间较大,且结点数目较多,因而算法对空间的要求可能根本无法得到满足。2并非算法效率的瓶颈所在。由于不是算法最费时间的地方,这里是否进行改进,显然是不会对整个算法构成太大影响的,若使用链式结构反而会显得操作过于繁琐。二、必要时采用链式存储结构。 上面我对使用顺序存储结构的条件进行了分析,最后就只剩下何时应该采用链式存储结构的问题了。 由于链式结构中指针操作确实较繁琐,并且速度也较慢,调试也不方便,因而大家一般都不太愿意用链式的存储结构。但是,这只是一般的观点,当链式结构

20、确实对算法有很大改进时,我们还是不得不进行考虑的。问题三 IOI99的地下城市。已知一个城市的地图,但未给出你的初始位置。你需要通过一系列的移动和探索,以确定初始时所在的位置。题目的限制是:1不能移动到有墙的方格。2只能探索当前所在位置四个方向上的相邻方格。在这两个限制条件下,要求我们的探索次数(不包括移动)尽可能的少。由于存储结构要由算法的需要确定,因此我们首先来确定问题的算法。经过对问题的分析,我们得出解题的基本思想:先假设所有无墙的方格都可能是初始位置,再通过探索一步步地缩小初始位置的范围,最终得到真正的初始位置。同时,为提高算法效率,我们还用到了分治的思想,使我们每一次探索都尽量多的缩

21、小初始位置的范围(使程序尽量减少对运气的依赖)。接着,我们来确定此题的存储结构。由于这道题的地图是一个二维的矩阵,所以一般来讲,采用顺序存储结构理所当然。但是,顺序存储结构在这道题中暴露了很大的缺点。我们所进行的最多的操作,一是对初始位置的范围进行筛选,二是判断要选择哪个位置进行探索。而这两种操作,所需要用到的数据,只是庞大地图中很少的一部分。如果采用顺序存储结构(如图3-1中阴影部分表示已标记),无论你需要用到多少数据,始终都要完全的遍历整个地图。 4 3 2 1 1 2 3 4 图3-1 head 图3-2然而,如果我们采用的是链式存储结构(如图3-2的链表),那么我们需要多少数据,就只会

22、遍历多少数据,这样不仅充分发挥了链式存储结构的优点,而且由于不需单独对某一个数据进行提取,每次都是对所有数据进行判断,从而避免了链式结构的最大缺点。我们使用链式存储结构,虽然没有降低问题的时间复杂度(链式存储结构在最坏情况下的存储量与顺序存储结构的存储量几乎相同),但由于体现了前文所述选择存储结构时扬长避短的原则,因而算法的效率也大为提高。(程序对不同数据的运行时间见表3-3)测试数据编号使用顺序存储结构的程序使用链式存储结构的程序10.06s0.02s21.73s0.07s31.14s43.86s0.14s532.84s0.21s6141.16s0.23s70.91s0.12s86.92s0

23、.29s96.10s1017.41s0.20s表3-3 (附使用链式存储结构的程序under.pas) 我们选择链式的存储结构,虽然操作上可能稍复杂一些,但由于改进了算法的瓶颈,算法的效率自然也今非昔比。由此可见,必要时选择链式结构这一方法,其效果是不容忽视的。 合理选择逻辑结构,由于牵涉建立数学模型的问题,可能大家都会比较注意。但是对存储结构的选择,由于不会对算法复杂度构成影响,所以比较容易忽视。那么,这种不能降低算法复杂度的方法是否需要重视呢?大家都知道,剪枝作为一种常用的优化算法的方法,被广泛地使用,但剪枝同样是无法改变算法的复杂度的。因此,作用与剪枝相似的存储结构的合理选择,也是同样很

24、值得重视的。 总之,我们在设计算法的过程中,必须充分考虑存储结构所带来的不同影响,选择最合理的存储结构。四、多种数据结构相结合上文所探讨的,都是如何对数据结构进行选择,其中包含了逻辑结构的选择和存储结构的选择,是一种具有较大普遍性的算法优化方法。对于多数的问题,我们都可以通过选择一种合理的逻辑结构和存储结构以达到优化算法的目的。但是,有些问题却往往不如人愿,要对这类问题的数据结构进行选择,常常会顾此失彼,有时甚至根本就不存在某一种合适的数据结构。此时,我们是无法选择出某一种合适的数据结构的,以上的方法就有些不太适用了。为解决数据结构难以选择的问题,我们可以采用将多种数据结构进行结合的方法。通过多种数据结构相结合,达到取长补短的作用,使不同的数据

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2