去年的今天,金庸與世長辭,當時Jerry在成都地鐵一號線下班的路上得知了這個消息,回到家當即寫了一篇文章來悼念:金庸的武俠世界和SAP的江湖。html
一年的時間轉瞬即逝,你們都忙碌於各自的生活,不少人對金老的離世已經淡忘了,不過Jerry這種金庸的死忠粉,對於這個一週年忌日仍是記得很清楚的。git
由於Jerry手上事情不少,沒時間在這個特殊的日子寫文章記念了,就發一小段代碼吧。github
需求:列出金庸任意一本小說裏出現的全部成語。web
實現:Jerry部署在Github上的一個web應用,連接以下:數組
jerrywang-sap.cn/FioriODataT…數據結構
首先點擊超連接「成語全集」:函數
點擊以後,存儲於該web應用本地存儲的一個文本文件裏的所有19830個成語,以樹的形式加載到內存中,並顯示在網頁上:微服務
而後複製一本金庸小說的內容,粘貼到網頁的「內容」區域,點擊按鈕「測試」:工具
能夠看到僅僅用了246毫秒,就將這部一百多萬字的《倚天屠龍記》裏出現的全部成語,以紅色高亮的方式高亮出來。學習
這個功能咋實現的?Chrome打開Jerry的網頁,F12開啓開發者工具,就能看到JavaScript源代碼,固然也能夠從個人Github上得到.
Jerry簡單講下實現原理。Web應用裏有一個文本文件,裏面維護了漢語裏所有的成語,經過分號分隔。
運行時,這些內容會被加載到內存中,構建成一棵樹,以下圖所示:
其中葉節點以屬性end爲true區分。
成語檢索的核心邏輯位於search函數裏,讓咱們用《笑傲江湖》裏一句響亮的口號「日月神教千秋萬載,一統江湖」來單步調試,瞭解其實現邏輯。
進入165行的外層while循環,再進入173行的內層for循環,檢測是否有測試字符串第一個字符「日」開頭的成語。由於成語是由4個字符組成,因此須要用內層for循環逐一試探,若是遇到tblCur.end爲true的元素,說明在測試字符串中發現了一個成語。
下圖是內層for循環第一次執行後的tblCur內容:
內層循環執行第二次,此時tblCur指向一棵由全部「日月」開頭的成語組成的樹:
執行內層循環的第三次迭代,由於在樹「日-月」這個分支下面沒有「神」這個節點,因此結束當前的內層循環,經過break返回到外層的while循環,進行輸入字符串第二個字符「月」的新一輪試探,以此類推。
最後從「千」這個字符出發,沿着內存中的樹通過路徑"秋-萬",最後來到end屬性爲true的葉節點「載」,記下「千」在輸入字符串中的偏移量,存到一個數組arrMatch中去。
待輸入字符串所有試探完畢後,根據arrMatch中存放的偏移量,高亮顯示對應的字符串,完成檢索。
樹這個數據結構在這個需求的實現裏有着完美的表現。
金庸雖然離開了咱們,但他筆下那些人物和發生的故事,將永遠流傳於這個世上。
要獲取更多Jerry的原創文章,請關注公衆號"汪子熙":