標籤:

如何提升 C++ Trie 樹的存取效率?

C++要做一個字典,我用了trie樹,從詞語開始建樹用了差不多3.8s,然後我想「序列化」到磁碟,每次直接讀取,但是最後發現也要3.8s。。。

我這裡的「序列化」不是boost裡面的,是一個深度優先的然後回退就輸出-1做標記。

有沒有其他方法序列化可以更快啊?謝謝~


你可以想辦法把節點分配到連續的內存里(就向資料庫的文件管理部分做的一樣),管理好連續內存里沒用上的部分,然後指針都用index代替,這樣讀寫文件就直接Creating a File Mapping Object 1G都不怕。

說來讀書的時候我也用類似的方法做過無前置知識的分詞系統,靠閱讀大量的文章提取文字之間潛在的關係的一些概率相關的東西,猜哪些字通常都在一起出現。一開始不僅慢,而且沒讀幾篇文章就撐爆內存了。後來用這種方法不僅擴大了數據量(主要是浪費的少),性能還提高了幾十倍。


首先,考慮用一種適合序列化的數據結構來實現 Trie,而不是直接用樹節點。

An Implementation of Double-Array Trie


https://github.com/atframework/atframe_utils/blob/master/include/string/ac_automation.h

你可以參考這個實現


Trie建樹的複雜度也是O(n*L)和遍歷一遍字典是一樣的,所以不要指望靠多牛逼的」序列化「方法來提升性能。

如果只是單次查詢,或者查詢成本遠低於建trie成本的話就不用搞什麼trie了,老實線性查找吧。

如果真的查詢量大,還有落地到磁碟的需求,那麼需要設計一下存儲的結構,比如最簡單的把結點換成塊連續存儲,指針換成下標表示,查詢的時候直接用mmap訪問避免數據全部load到內存。

最後,折騰這種東西一定得把磁碟換成SSD的。


可以參考hankcs的基於AC自動機的雙數組trie樹:

hankcs/AhoCorasickDoubleArrayTrie


推薦閱讀:

學習C++語言重點應該當在哪裡?
C++中循環中的auto是利用了迭代器的機制嗎?
codeblocks寫代碼有時候會自動補全,有時候不補全?

TAG:C | 數據結構 |