紅黑樹與Hash的區別與選擇

什麼是Hash

Hash,也能夠稱爲「散列」,就是把任意長度的輸入,經過散列算法,變換成固定長度的輸出,該輸出就是散列值。這是一種壓縮映射,也就是,散列值的空間一般遠小於輸入的空間,不一樣的輸入可能會散列成相同的輸出(也就是多對一的關係)。 html

哈希表的構造

在全部的線性數據結構中,數組的定位速度最快,由於它可經過數組下標直接定位到相應的數組空間,就不須要一個個查找。而哈希表就是利用數組這個可以快速定位數據的結構解決以上的問題的。 c++

"數組能夠經過下標直接定位到相應的空間」,對就是這句,哈希表的作法其實很簡單,就是把Key經過一 個固定的算法函數既所謂的哈希函數轉換成一個整型數字,而後就將該數字對數組長度進行取餘,取餘結果就看成數組的下標,將value存儲在以該數字爲下標 的數組空間裏,而當使用哈希表進行查詢的時候,就是再次使用哈希函數將key轉換爲對應的數組下標,並定位到該空間獲取value,如此一來,就能夠充分 利用到數組的定位性能進行數據定位。 算法

例如: 若是一個hash函數是這樣的, 數組

index = value % 5; 安全

以下圖中,左邊爲一個長度爲5的指針數據,下標從0到4,每一個數據元素都是一個鏈表的頭指針,這樣經過value%5就造成了一種一對多的關係,縮小了查找的範圍。 數據結構

雖然咱們不但願發生衝突(同一個key有多個value),但實際上發生衝突的可能性還是存在的。當關鍵字值域遠大於哈希表的長度,並且事先並不知道關鍵字的具體取值時。衝突就不免會發生。另外,當關鍵字的實際取值大於哈希表的長度時,並且表中已裝滿了記錄,若是插入一個新記錄,不只發生衝突,並且還會發生溢出。所以,處理衝突和溢出是哈希技術中的兩個重要問題。通常有開放地址法、鏈地址法。 函數

看到了一個叫作One-Way Hash的算法(來自暴雪的hash算法)。 性能

若是說兩個不一樣的字符串通過一個哈希算法獲得的入口點一致有可能,但用三個不一樣的哈希算法算出的入口點都一致,那幾乎能夠確定是不可能的事了,這個概率是1:18889465931478580854784,大概是10的 22.3次方分之一,對一個遊戲程序來講足夠安全了。第一個hash值做爲用來定位,另外兩個hash值用來檢測。 spa

Hash的實例JDK7與JDK8中HashMap的實現 .net

適用範圍   

  快速查找,刪除的基本數據結構,一般須要總數據量能夠放入內存

什麼是Map

Map是c++標準庫STL提供的一類關聯式容器,提供key-value的存儲和查找功能。

Map是基於紅黑樹的(一樣set也是)(Java中有基於Hash實現的HashMap和HashSet),那麼它的查找速度是log(n)級別的。

它的優勢是佔用內存小。

Hash與Map的區別

權衡三個因素: 查找速度, 數據量, 內存使用,可擴展性,有序性。
整體來講,hash查找速度會比RB樹快,並且查找速度基本和數據量大小無關,屬於常數級別;而RB樹的查找速度是log(n)級別。並不必定常數就比log(n) 小,hash還有hash函數的耗時,明白了吧,若是你考慮效率,特別是在元素達到必定數量級時,考慮考慮hash。但若你對內存使用特別嚴格, 但願程序儘量少消耗內存,那麼必定要當心,hash可能會讓你陷入尷尬,特別是當你的hash對象特別多時,你就更沒法控制了,並且 hash的構造速度較慢。

紅黑樹並不適應全部應用樹的領域。若是數據基本上是靜態的,那麼讓他們待在他們可以插入,而且不影響平衡的地方會具備更好的性能。若是數據徹底是靜態的,例如,作一個哈希表,性能可能會更好一些。

在實際的系統中,例如,須要使用動態規則的防火牆系統,使用紅黑樹而不是散列表被實踐證實具備更好的伸縮性。Linux內核在管理vm_area_struct時就是採用了紅黑樹來維護內存塊的。

紅黑樹是有序的,Hash是無序的,根據需求來選擇。

拿紅黑樹實現的Map和Hash實現的HashMap相比:

若是隻須要判斷Map中某個值是否存在之類的操做,固然是Hash實現的要更加高效。

若是是須要將兩個Map求並集交集差集等大量比較操做,就是紅黑樹實現的Map更加高效。

Reference:

1. http://www.cnblogs.com/coder2012/p/3386101.html

2. http://www.lxway.com/852122226.htm

3. http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/u012609067/article/details/35849887

相關文章
相關標籤/搜索