hash_set,hash_map,hash_multiset,hash_multimap

上面四中容器都基於hashtable這種底層的機制。二叉搜索樹具有對數平均時間的表現,但這樣的表現簡歷在輸入數據有足夠的隨機性這一假設上。而hashtable這一數據結構在插入,刪除,搜尋等操作上都具有“常數平均時間”,而且這種表現不依賴輸入元素的隨機性。

在STL中hashtable的實現是使用開鏈法去解決不同元素落在同一個存儲單元中。這種做法是在每一個表格元素中維護一個list,然後我們在那個list身上執行元素的插入、搜尋、刪除等操作。


如上圖,在STL中,hash表中的元素使用一個vector來表示,而vector中的每個元素都是一個list的頭指針。list中的元素真正存放了插入的元素。

在STL的實現中,用質數來設計表格vector的大小,先將28個質數(大約呈現兩倍的關係)計算好備用。53,97,193,389,769..........4294967291。當初始化時,hashtable選擇一個大於初始化數據的最小質數作爲vetor的大小。那麼當插入的個數增加,可能需要將vector的容量增加,在STL中這個判斷原則比較特殊:當插入了一個新的數據之後,若在這個list上的數據個數大於了vector當前的元素個數,那麼就需要進行重建,選下一個質數爲vector的大小,再將原來的數據重新計算放入新的hashtable

插入數據分爲兩種,一種是允許重複,另一種是不允許重複。如果是不允許重複,定位到確定的list之後,需要遍歷該list查看該鍵值是否已經存在,若不存在則插入,否則直接返回。若允許重複,還是需要檢查,如果之前鍵值存在,那麼存放在該鍵值之後,若不存在放在該list的頭部。(原因不詳)

在hash functions中我們要將輸入的值進行操作輸出一個可以進行模運算的值。對於大多數的類型,hash function什麼也沒做,只是忠實的返回了原值,但是對於字符串char*,設計了一個轉換函數

size_t __stl_hash_string(const char *s)

{

unsigned long h = 0;

for(; *s;++s)

h = 5*h + *s;

return size_t(h);

}

這裏爲什麼用5這個值原因不明。

有了hashtable的底層實現,hash_set, hash_map,hash_multi_set, hash_multimap就不難理解了,這四種容器都是使用了hashtable的機制實現,set和map的區別是set只有一個鍵值,map有一個鍵值和一個實值,按照鍵值進行hash,實值可以修改。multi和沒有multi的區別就是是否允許重複的鍵值出現。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章