讀古今文學網 > 算法神探:一部谷歌首席工程師寫的CS小說 > 13 用棧和隊列搜索 >

13 用棧和隊列搜索

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教授講義

信息是設計高效算法時不可或缺的要素。我們儲存信息的方式和使用的數據結構,不僅會影響到算法的效率,也會決定算法的工作原理。從之前課上學到的深度優先搜索和廣度優先搜索中,我們已經可以看出數據結構的重要性。雖然這兩種搜索的算法在概念上是相似的,但我們用來儲存狀態的數據結構(棧或隊列)不同,這在很大程度上決定了搜索會怎麼進行下去。

選擇數據結構時一定要小心,因為數據結構應該符合算法的需求。假設你選擇使用圖來存放一串排好序的數字,就算你能想方設法地來維護這列數字的順序,也不能高效地進行二分搜索。這是因為圖這種數據結構限制了我們存取數據的方式,我們不能像數組那樣用下標序號來存取數字。這樣一來,要想找到一個下標對應的數字,我們就必須進行一次線性查找,沿著圖中的邊逐個找下去。