Frank努力将烧焦面包的画面从脑海中消除,重新将注意力集中到他们目前的处境。他们现在被困在一间房间里,里面装满了即将燃烧起来的羊皮纸。火势目前还很小,只烧到了那一摞纸最边上的几张散页。但是一旦那一摞纸燃烧起来,火势将无法控制。
Socks爬向门的方向,随后将身体靠在门上。“它锁住了吗?”他问道。
Frank心中想到了无数嘲讽Socks的方式,但最终他只是简单地点了点头。“你能打开它吗?”他问道,“这是一个老式的两针式的锁,不会有太多种组合方式的。”
Socks摇了摇头。“没时间了。不过我知道一个软化铁的咒语。当然用了它这个门就彻底毁了。不过当下这种情况,门的好坏已经无所谓了。”
他拿起自己的魔杖,立刻开始行动。他念着咒语,手不断在门上游走。他的手经过的地方逐渐长出了铁锈,很快就铺满了这个铁门的表面。不到一分钟后,Socks退后了一步。铁门看起来已经锈透了,但不管怎么说,毕竟还是铁做的。
“铁门现在应该比之前要脆弱很多了,”Socks说道,他又后退一步,期待地看着Frank,仿佛在说:“现在你随时可以直接破门而出了。”
Frank也退后几步,两眼打量着那扇门。“有多脆弱?”Frank问道,“你说的脆弱是像牙签那样,还是像一块厚木板那样?”
“额……肯定比一般的铁脆弱多了,”Socks回答道,“我让它多了很多铁锈。虽然门很厚,但我想它现在应该相当脆弱了。”
Frank低吟了一声,他深呼吸了一下,积蓄着力量。然后,他放低自己的肩膀,冲向了门。撞上的那一下Frank的整个身体都震了一下,但他终究还是冲过去了。
冲过门的Frank四肢张开地躺在地上,而他四周的空气中已充满了铁锈。
Socks急忙跑到他身边。“你还好吗?”他回头望了门一眼,随即笑道,“成功了!”他骄傲地说道,“门是不是很脆弱?撞上去的感觉如何?”
“像撞一尺厚的木头一样,”Frank说道,“疼死了。”
Socks脸上的笑容暗淡了一些,说道:“哦……”
Frank努力站起来,肩膀非常疼,明天那里肯定会淤青一大片。但目前,和逃离火海的开心相比,那些都不算什么。
“该走了。”Frank一边走向下一个房间,一边说道。
“你还记得怎么回去吗?”Socks问道。
“当然,”Frank回答道,“我们是用深度优先搜索找到这里的。我们沿着栈回去就好了。”
“栈?”Socks边跟上Frank边问道。
“对,”Frank一边在心中回味着刚刚的逃脱,一边回答道,“我们可以用不同的数据结构来区别这两种不同的搜索。比如,广度优先搜索用的是队列,而深度优先搜索用的则是栈。”Frank此时竟然给出了教科书般的答案,简直像Notation附体了似的。
“实际上,在进行深度优先搜索的时候,有很多种可以用栈来记录目前选项的方法。有些人喜欢用栈来记录下一列他们还未探索过的房间,就像你在广度优先搜索中用的队列一样。但我喜欢用另一种方法。
“你可以用一个栈来存放你当前走过的路径上的房间。每当探索到一个新房间时,就将它推入到这个栈中。
“当你倒退时,就将那个房间从栈中推出,并回到它之前的那个房间。这样,你永远都能知道如何倒退回起点。为了让倒退的过程容易些,我还将房间都编了号。”
“我以为只要每次回到我们之前最后一个需要做决定的分叉口就行了。”Socks说道。
“其实就是这样,”Frank说道,“但是将目前路径上的房间放在一个栈里可以让这样的做法变得更容易。你只要不断地倒退,并将房间从栈中推出,直到你倒退到一个还没有完全探索完的房间为止。”
Socks看起来十分佩服Frank,说道:“你把我们探索过的房间都写下来了?”
“我把那个栈记在脑中,并且用粉笔对房间都编过号了,”Frank回答道,“我之前说过,这不是我第一次用深度优先搜索了。我们需要倒退七个房间。”
他们匆忙地跑过了两个黑暗的房间。Socks突然想起手中的魔杖。随着他低吟着点火的咒语,他手中魔杖的顶端冒出了一团蓝色火焰。
Frank紧张地看了眼魔杖。“把它握紧一些。”他说道。
又走过了三个房间后,Socks突然问道:“那队列呢?”
“队列怎么了?”Frank问道。
“你说过它们是用来做广度优先搜索的。”
“对,”Frank说道,“你之前用过的魔法列表就是一个队列。在广度优先搜索中,这个队列是用来记录还没有探索过的选择。不过每次是将和当前状态相邻的状态加到队列的尾部,而不是将当前状态推入栈中。”
“那么在深度优先搜索的时候,你是用栈来记录没有探索过的状态,还是记录当前路径呢?”Socks问道。对于一个正从废弃监狱中逃离袭击者的人来说,他的语气听着出奇兴奋。
“只要你足够细心,两种方法都可以。”Frank说道。
“我从来没有从栈和队列的角度来想过搜索,”Socks沉思道,“肯定还有很多数据结构也被我忽视了。我打赌解绳之咒也用到了一些数据结构。”
Frank完全无视了Socks的自言自语,他们继续向出口走着。他们走得很快,不过是为了逃跑,而不是继续探索。Frank觉得袭击他们的人肯定已经走了,因为并没有人试图阻止他们逃跑。并且在烧掉证据之后,袭击者也并不需要继续留在这了。
过了几分钟,他们找到了出口,并冲了出去。他们身后溢出了一缕黑烟。到现在,大火应该已经把所有的纸都烧光了。他们所有的线索都被毁掉了。
警用算法导论:栈和队列Ⅱ
节选自Drecker教授讲义
信息是设计高效算法时不可或缺的要素。我们储存信息的方式和使用的数据结构,不仅会影响到算法的效率,也会决定算法的工作原理。从之前课上学到的深度优先搜索和广度优先搜索中,我们已经可以看出数据结构的重要性。虽然这两种搜索的算法在概念上是相似的,但我们用来储存状态的数据结构(栈或队列)不同,这在很大程度上决定了搜索会怎么进行下去。
选择数据结构时一定要小心,因为数据结构应该符合算法的需求。假设你选择使用图来存放一串排好序的数字,就算你能想方设法地来维护这列数字的顺序,也不能高效地进行二分搜索。这是因为图这种数据结构限制了我们存取数据的方式,我们不能像数组那样用下标序号来存取数字。这样一来,要想找到一个下标对应的数字,我们就必须进行一次线性查找,沿着图中的边逐个找下去。