第七周 - 20180521

C++中map/unodered_map選擇和比較

在寫LycorisNet的過程中,底層的數(shù)據(jù)結構大量使用了map,試圖加快算法的運行速度。Lycoris初代的版本是采用Go語言開發(fā)的,Golang中“稀少”的數(shù)據(jù)結構讓我最終不得不選擇基于哈希的map。后期為了進一步加速,決定全部使用C++ 11進行重構。

然而框架搭建好了以后,發(fā)現(xiàn)C++ 11標準庫中map默認為紅黑樹的實現(xiàn),此外其還內置了基于哈希實現(xiàn)的unodered_map。出于極客對極致性能的追求,有必要對兩種map進行比較和擇優(yōu)。

Map是STL的一個關聯(lián)容器,它提供一對一(其中第一個可以稱為關鍵字,每個關鍵字只能在map中出現(xiàn)一次,第二個可能稱為該關鍵字的值)的數(shù)據(jù)處理能力,由于這個特性,它完成有可能在我們處理一對一數(shù)據(jù)的時候,在編程上提供快速通道。這里說下map內部數(shù)據(jù)的組織,map內部自建一顆紅黑樹(一種非嚴格意義上的平衡二叉樹),這顆樹具有對數(shù)據(jù)自動排序的功能,所以在map內部所有的數(shù)據(jù)都是有序的。

boost::unordered_map, 它與 stl::map的區(qū)別就是,stl::map是按照operator<比較判斷元素是否相同,以及比較元素的大小,然后選擇合適的位置插入到樹中。所以,如果對map進行遍歷(中序遍歷)的話,輸出的結果是有序的。順序就是按照operator< 定義的大小排序。

而boost::unordered_map是計算元素的Hash值,根據(jù)Hash值判斷元素是否相同。所以,對unordered_map進行遍歷,結果是無序的。

用法的區(qū)別就是,stl::map 的key需要定義operator< 。 而boost::unordered_map需要定義hash_value函數(shù)并且重載operator==。對于內置類型,如string,這些都不用操心。對于自定義的類型做key,就需要自己重載operator< 或者hash_value()了。?

人們往往會更傾向于一個理論——在不需要排序的情況下盡量選擇給予哈希的實現(xiàn),但在真正實現(xiàn)中往往不是這樣。至少在Lycoris中,unodered_map并不比map提高了性能,一方面是由于散列函數(shù)(哈希函數(shù))選擇不當(我嘗試過大多數(shù)包括異或移位),另一方面可能由于map并不是算法的瓶頸。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容