利用树结构求解经栈操作的所有序列到达问题.docVIP

利用树结构求解经栈操作的所有序列到达问题.doc

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
利用树结构求解经栈操作的所有序列到达问题 浙江省慈溪实验中学 张利波 315300 第八届信息学初赛普及组问题求解第一题: 如下图,有一个无穷大的栈S,在栈的右边排列着1,2,3,4,5共五个车厢。其中每个车厢可以向左行走,也可以进入栈S让后面的车厢通过。现已知第一个到达出口的是3号车厢,请写出所有可能的到达出口的车厢排列总数(不必给出每种排列)。 出口← ← 1 2 3 4 5 S↓ 【模拟分析】 这是一例典型的车辆调度题目,其本质是求经过栈操作的到达出口的所有序列,若单纯求数量,可以套用公式C(2n,n)/(n+1),但要进一步排列所有序列,则需要运用其他方法或结构实现,以前有文章提到运用0、1数字串实现(具体可参看《全国青少年信息学联赛培训教材(复赛篇)》(主编:李建江 马茂年)P88 例15火车转轨问题),今天笔者将采用树结构来实现某一状态下(已知首个到达元素)所有符合的输出序列。 以上题为例分析,原始序列1、2、3、4、5,第一个到达出口的是3。我们不妨以当前到达出口元素为界限,分成左右两部分。 左边:根据原始序列,结合当前到达出口元素,说明该元素左边的所有元素目前处在栈中,若出栈,根据“先进后出”特点,只能选择最近一次入栈的元素2。对于元素较多的一般情况,左边范围的元素作为下一个到达出口的元素,是在其左边,距其最近允许访问的元素,元素若存在,仅有一个。 右边:根据当前到达出口的元素,其右元素可以入栈,也可以不入栈(或入栈后马上出栈)。如果选择下一个到达出口的元素,那么可以是右边元素集合中的任一个,且不应遗漏。 34 3 4 5 2 图1 那么后继结点,该如何再扩展呢?即在一般情况下,某种状态下到达出口的元素,同样适合于上面分析,按左右分开,左边选择最近的一个未访问的元素(相当于最后一次入栈元素),右边选择所有未访问过的元素,之所以要求未访问,主要避免重复访问。如图1,若当前元素为2,其下一个到达的元素中,应剔除3,即剔除该结点的祖先(可以通过逐层剔除父结点办法实现),而其他后继子结点运用同样方法,以此继续发展当前元素的下一层结点。由于涉及到是否访问,在编程实现中需要将原始序列的每个元素添加一个访问标记flag。 根据以上分析,我们可以把发展后继子结点的方法看成深度和宽度结合的遍历方式,对于某个元素,先产生其下一层的所有子结点,再在子结点中选择一个,继续产生其下一层的子结点,直到树的深度(到达序列个数)等于原始序列的数量。这个过程总的方向是先深度,后宽度,但在发展深度的一层中先满足该层上的宽度。 图2③②④ 图2 ③ ② ④ ⑤ ① ④ ⑤ ② ⑤ ④ ④ ⑤ ① ⑤ ④ ① ⑤ ② ② ⑤ ④ ⑤ ① ① ⑤ ① ① ① 【编程分析】 data12345 data 1 2 3 4 5 flag true true true true true 原始序列初始状态下用数组表示如右: 其中flag=true表示该元素允许访问。 初始状态下,先由3写入数组,填写其相关参数,pre=0,dep=0,引入指针变量p、q、succ,其中p指向当前扩展的元素下标(此时为1),q指向填写扩充元素的下标(此时为2),succ指向扩展的第1个结点下标,用于深度扩展时,将该结点作为扩展时的当前点执行循环操作。然后根据原始序列表格,从左边找到最近的元素2,写入数组q位置,填写参数,a[q].data:=d[j].data,a[q].pre:=p,a[q].dep:=a[p].dep+1,此时,q后移一位,即q:=q+1,左边结束。同样从右边找到所有未访问的元素4,5,可以用循环依次写入a[q]位置,填写参数,同时q后移一位,循环结束,表示左右两边元素已经全部写入数组,即当前元素的下一层结点扩展完成。为避免后继结点对祖先的重复访问,扩展完毕后需把当前元素的访问标记改为false,同时检验当前结点深度是否为最深,若为最深,需回溯,如何回溯后面将有分析。若不为最深,即还需沿深度方向继续扩展结点。这时,将下一个扩展的元素,指向已扩展该层上首个元素(succ),即p=succ,q不变,succ=q,继续扩展下一层的结点,直到深度为最深max-1。若完成第一个到达序列(即32145)后,数组a元素分布情况,p、q、succ指针情况如下表所示: 下标 1 2 3 4 5 6 7 8 9 10 11 12 data 3 2 4 5 1 4 5 4 5 5 pre 0 1 1 1 2 2 2 5 5 8 dep 0 1 1 1 2 2 2 3 3 4 ↑ p ↑ ↑ q succ 此时,由于深度达到最深max-1,即产生了一个新的序列,该状态下,d[]数组中的访问标记已经全部变成false,即不允许再次访问了。此时要进行回溯

文档评论(0)

有志者事竟成 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

版权声明书
用户编号:7114163151000053

1亿VIP精品文档

相关文档