讀古今文學網 > 算法神探:一部谷歌首席工程師寫的CS小說 > 24 用優先隊列進行調查 >

24 用優先隊列進行調查

「Donavan警長!」Notation走進辦公室時,脫口而出。

「我想當面向您道歉,我在工作時間之外,未經授權就去調查案子。但這既是Frank調查的案子,也是我的,如果他報告……」

「這案子怎麼變成你的了,Notation警官?」警長打斷她,「我記得我派你去查假冒溜溜球的案子。可你為什麼在Crannock的農場調查被盜的文件?」

「我在跟蹤一條線索……」Notation說。

「你在跟蹤一條線索?」警長打斷道,「你的所有報告裡,我沒看到任何關於Array Cart的報告。」

「我是那天早上才想到的。」Notation解釋道。

「所以,你決定自己跟蹤這條線索,而不向負責這個案子的偵探報告?」

Frank皺起了眉頭。警長特別執著於照章辦事,在警長看來,得到線索不及時報告是非常嚴重的事情。從Notation慌張的言辭中,Frank看出她也是這麼想的。

「我當時已經在農場的附近,」她說,「發現……」

「有線索?」Frank問。

「我記得失竊當晚,」她說,「我剛做完我的晚間值班報告,就看到窗外一輛奇怪的推車。當時我也沒多想,因為魚販們總是喜歡用各種奇怪的推車。我以為是早晨魚販們交貨用的。」

她轉向警長,目光中流露出懇求之情。「這條線索看起來不大靠譜,」她解釋道,「我覺得這條線索或許是條死胡同,那車可能只是交貨用的。所以在查出更多情況前,我並不想報告。」

「然後你就和Frank一起查了幾乎兩整天?」警長說。

「我們發現了一些更有用的線索。」Notation道。

「Notation警官,」警長厲聲道,「不知道是哪位前警長的鬼魂在引導你這樣做。現在每個人都要遵守規章制度,而你沒有。」

Notation死死地盯著地面:「我明白了,長官。」

「不,」警長說,「我不確定你是不是真的明白。但你會有足夠的時間去反省。你被停職了,等候通知。」

Notation哆嗦了一下,但沒有抗議。

警長轉向Frank說:「Frank,你有工作要做了。」

當Notation轉身離開時,她的視線凝固在了掛在牆上的Fredrick國王的肖像上。她似乎陷入了沉思。

「警長,」她突然停住說,「你有優先隊列嗎?」

Frank努力地回憶了一下,最後想起來他的一位教授曾在課堂上講過Fredrick國王是如何推廣優先隊列方案的。

在Fredrick成為國王之前,他會傾聽王國公民的投訴。由於時間緊迫,市民投訴繁多,他被迫需要制定一個優先隊列方案。畢竟Fredrick王子一次能忍受的抱怨是有限的。

開始時,Fredrick王子試過使用投訴棧,優先選擇處理最新的投訴,但後來他發現這樣會錯過那些重要的但很久以前的投訴。然後他嘗試使用投訴隊列,優先選擇處理時間最早的投訴,然後他發現這樣又會錯過重要的近期投訴。最後,他採用了一種新的數據結構——優先隊列——使得他每次都可以先處理最重要的投訴。

「優先隊列?」警長問,顯然被這個突如其來的問題問蒙了。警長訓完話後幾乎沒有人敢接話。他們只是慢吞吞地小心翼翼地走出辦公室,或者在某些情況下,還會被關在一間黑暗的雜物室裡待上幾小時。

「一種數據結構」,Notation胸有成竹地解釋道,「就像普通的隊列,你可以對元素進行入隊和出隊操作。區別是為每個元素增加了一個重要性的優先級分數。當一個元素出隊時,優先隊列就會為你提供下一個最重要的元素。」

看到警長和Frank貌似有些不理解,Notation舉了一個例子:「如果我插入四個元素,優先級分別為1、2、4和3,那麼我會按4、3、2、1的順序提取它們。」

「我知道什麼是優先隊列,」警長說,「我們用它來存儲噪聲投訴清單。叫得越響,優先級越高,所以我們總是先解決最糟糕的情況。我聽說他們也採用這種方法來處理附近污水臭味的投訴,雖然看起來那裡的所有事項的優先級都一樣——都令人非常難以忍受。不過,你想說什麼?」

「您這裡有優先隊列嗎?」Notation問道。

警長搖搖頭,感到迷惑不解,並壓制著自己的憤怒:「沒有多餘的了」,他說,「所有的優先隊列都已經投入了使用,有一個用於噪聲投訴,有三個用於不同類型的犯罪,還有一個用於最高通緝犯,最後一個用於度假申請的安排。你想說什麼?」

「最佳優先搜索。」Notation說。

「最佳優先搜索?」警長問道,「Frank告訴我,他使用的就是最佳優先搜索。」

「沒錯。」Frank點頭道。

「優先隊列會更有效率,」Notation解釋道,「每次我們找到一條新線索,就可以把它放到優先隊列中,通過其得分來顯示該線索的質量。接下來,當我們準備調查下一條線索時,就可以從優先隊列中提取最有用的線索。這樣,我們總會按照下一條最有用的線索進行調查。」

Frank歎了口氣,搖了搖頭。他知道警長完全能猜出這番談話的目的。警長擅長給大家上課,他不會凶巴巴地罵人或說髒話,但會以平靜的方式讓一名新警官意識到自己的愚蠢。「你之前是怎麼做的?」警長耐心地問。

「我把線索都記在一個筆記本裡,」Notation答道,「每次我們準備調查一條新的線索時,我就會看一遍整個清單,找到最好的那個。」

「那你有多少條線索呢?」警長問道,「平均而言。」

「平均而言?」Notation想了一會說道,「我猜有二到五條吧。」

「你想讓我使用優先隊列來處理只有二到五條記錄的列表嗎?」如果警長採用他一貫吼叫的方式來問,那這個問題聽起來可能不太嚴重。相反,他的冷靜和耐心的口氣讓整個討論的不必要性更突顯了。

Notation臉紅了。「嗯,優先隊列並不是很昂貴……」她開口道,話沒說完又嚥回去。

「Notation警官,」警長說,「我同意優先隊列對於最佳優先搜索很有用。待會我就可以訂購一套全新的系統,每個偵探配一套。但現在你還用不到,因為你還沒有足夠多的線索,而且更重要的是,這案子不歸你管。」

警長越說,Notation的臉越紅,現在已紅得像甜菜湯了。她深吸一口氣,直視警長的眼睛,咕噥道:「我明白了,長官。」

Frank感到非常遺憾。Notation犯了典型的菜鳥錯誤,過度優化解決方案。他得告訴她使用優先隊列來追蹤線索的想法是完全合理的,事實上,他一直在使用優先隊列。然而,她問問題的時機卻糟到不能更糟了。

「Notation,」警長繼續說,「你在這裡很有前途。你聰明、上進、有良好的直覺。但是你必須學會服從命令。別最後像Frank那樣。」

Notation想開口抗議,但她看了一眼Frank,扮了個鬼臉,然後緊閉著嘴,一聲不吭。她微微點點頭,敬了個禮,大步走出辦公室。

「Frank,你現在有得忙活了。去吧。」

Frank轉身跟著Notation出去,連頭都懶得點一下。

直到來到樓梯前,Frank才開口說話。

「你應該知道Orb區有一個行家,能幫你做便宜的優先隊列,他叫Heaperous。他只在上午工作,所以你得等到明天才能找他。」

Notation停了下來,非常疑慮地看了他一眼,問道:「你為什麼要告訴我這個,Frank?」

Frank努力做出同情的表情:「我聽了警長的許多長篇大論。更重要的是,我知道好的數據結構對於調查的價值。」

「如果好的數據結構更有價值,那你為什麼不使用優先隊列?」她反問。

Frank惱怒地看著她說:「我當然在用優先隊列。一開始我就一直在用。你以為我一直在用腦袋瓜子記所有的線索嗎?」

「什麼?」Notation道,「搞了半天,你一直在用優先隊列啊?你為什麼不跟警長說?」

Frank笑道:「菜鳥,你還要多瞭解一下警長。首先,警長在對任何東西誇誇其談時,你不要去打斷他。我曾經看到一名偵探被調職去做一個月的筆錄,就是因為警長在大聲評論豆腐的時候被他打斷了。」

Notation盯著Frank,不知說什麼好。

「關鍵是,」Frank繼續道,「有時候你需要自己動手。如果優先隊列可以幫到你,不要等著批准。出去買一個用就行。」

Notation考慮了一下這個建議。最後她點了點頭:「從技術上而言,購買自己的裝備不違反任何政策。謝謝你,Frank。」

Notation臉上的興奮幾乎讓Frank感到內疚。任何鎮上行家商店裡都可以做優先隊列,大多數都與Heaperous的價格相當。但Heaperous所在的Orb區是市區範圍內最遠的一個,之所以告訴Notation這家店,是因為Frank需要確保Notation能在盡量長的一段時間裡不妨礙自己做事。

警用算法導論:優先隊列

節選自Drecker教授講義

在警察的職業裡會碰到的所有數據結構中,我保證最有價值的是優先隊列。就像數據棧和隊列,優先隊列數據結構讓你能插入數據,然後按特定的順序刪除數據。棧和隊列的執行順序由插入的元素決定,而優先隊列通過優先級遞減來給數據排序。下一個刪除的元素是當前隊列中優先級最高的元素,而無論該元素是何時插入的。

每個插入優先隊列的元素也必須有優先級,或者叫分數。這可以是元素本身的價值,也可以根據不同的函數計算得來。

接下來我們來看看這個有關噪聲投訴的案例,它是根據噪聲的嚴重性進行優先排序的。如果按照以下順序插入這些投訴:

「Exponentiated Expresso的夥計們」(得分=3)

「Crab』s Pinch船夫號子大賽」(得分=6)

「Swinson農夫的兔子」(得分=1)

「Swinson農夫的公雞」(得分=5)

「Swinson農夫」(得分=7)

那麼從優先隊列中檢索的順序如下:

「Swinson農夫」(得分=7)

「Crab』s Pinch船夫號子大賽」(得分=6)

「Swinson農夫的公雞」(得分=5)

「Exponentiated Expresso的夥計們」(得分=3)

「Swinson農夫的兔子」(得分=1)

注意,優先隊列中的數據並不一定是被排好序的,只能保證按優先級高低順序提取。在以後的講義中你將看到,稱為堆的數據結構是一種實現優先隊列的有效方式,這種方式並不會完全按順序保存數據。

首都的警察局採用很多種不同的優先級判定函數。如你所料,最有爭議的優先隊列正是度假優先隊列。這個隊列僅按照當前剩餘假期的天數來排序。之前有人提議過加入其他優先級因素,都被拒絕了。無論你選擇的度假地是冰川、海灘或沼澤,都將被平等對待——只看你剩餘的假期天數。當然,這樣的優先隊列最重視公平。它將確保下一名休假的警官是本年度休假最少的警官。