【STL源码剖析读书笔记】【第5章】关联式容器之hashtable
1、hashtable在插入、刪除、搜尋操作上具有“常數(shù)平均時間”的表現(xiàn),不依賴輸入元素的隨機性。
2、hashtable通過hashfunction將元素映射到不同的位置,但當不同的元素通過hash function映射到相同的位置時,便產(chǎn)生了“碰撞”問題。解決碰撞問題的方法主要有線性探測、二次探測、開鏈法等。
3、線性探測
當hash function計算出某個元素的插入位置,而該位置的空間已不可用時,循序往下尋找下一可用位置(到達尾端時繞到頭部繼續(xù)尋找),會產(chǎn)生primary clustering問題。
4、二次探測
當hash function計算出某個元素的插入位置為H,而該位置的空間已被占用,就嘗試H+12、H+22…,會產(chǎn)生secondary clustering問題。
5、開鏈
在每一個表格元素中維護一個list:hash function為我們分配某個list,在那個list上進行元素插入、刪除、搜尋等操作。SGI STL解決碰撞問題的方法就是此方法。
6、hashtable節(jié)點定義:
template <class Value>
struct __hashtable_node
{__hashtable_node* next;Value val;
}; 7、hashtable的迭代器
hashtable迭代器必須永遠維系與整個“buckets vector”的關(guān)系,并記錄目前所知節(jié)點。hashtable的迭代器沒有后退操作,也沒有逆向迭代器。
8、hashtable的數(shù)據(jù)結(jié)構(gòu)
template <class Value, class Key, class HashFcn,class ExtractKey, class EqualKey,class Alloc> value:節(jié)點的實值類別
?key:節(jié)點的鍵值類別
?HashFcn:hash function函數(shù)類別
?ExtractKey:從節(jié)點中取出鍵值的方法
?EqualKey:判斷鍵值相同與否的方法
Alloc:空間配置器,默認使用std::alloc
9、hashtable的構(gòu)造與內(nèi)存管理
節(jié)點配置函數(shù)與節(jié)點釋放函數(shù)
node* new_node(const value_type& obj){node* n = node_allocator::allocate();n->next = 0;__STL_TRY {construct(&n->val, obj);return n;}__STL_UNWIND(node_allocator::deallocate(n));}void delete_node(node* n){destroy(&n->val);node_allocator::deallocate(n);}
表格重建操作
resize()
{
表格是否需要重建判斷原則:拿元素個數(shù)和bucket vector的大小來比,如果前者比后者大就重建表格。因此,每個bucket(list)的最大容量和bucket vector的大小相同。如果要重建,找出下一個質(zhì)數(shù)作為vector的大小,建立新的buckets處理每一個舊的bucket{建立一個新節(jié)點指向節(jié)點所指的串行的起始節(jié)點處理每一個舊bucket所含串行的每一個節(jié)點{找出節(jié)點落在哪一個新的bucket內(nèi)令舊bucket指向其所指的串行的下一個節(jié)點將當前節(jié)點插入到新的bucket內(nèi),成為其串行的第一個節(jié)點回到舊bucket所指的待處理串行,準備處理下一個節(jié)點
}
}新舊兩個buckets對調(diào),如果雙方大小不同,大的會變小,小的會變大
離開時釋放temp的內(nèi)存
}
插入操作
insert_unique(const value_type& obj)//不允許元素重復
{resize(num_elements+1);//判斷是否需要重整表格return insert_unique_noresize(obj);
}
insert_unique_noresize(obj)
{計算出obj應位于哪個bucket令first指向bucket對應的串行的頭部如果bucket已經(jīng)被占用,檢查bucket對應的整個鏈表如果發(fā)現(xiàn)鏈表中有相同的元素,就立即返回否則產(chǎn)生新節(jié)點,令新節(jié)點為鏈表的第一個節(jié)點,節(jié)點個數(shù)加1
}
insert_equal(const value_type& obj)//允許元素重復
{resize(num_elements+1);//判斷是否需要重整表格return insert_equal_noresize(obj);
}
insert_equal_noresize(obj)
{計算出obj應位于哪個bucket令first指向bucket對應的串行的頭部如果bucket已經(jīng)被占用,檢查bucket對應的整個鏈表如果發(fā)現(xiàn)鏈表中有相同元素,則產(chǎn)生新節(jié)點,插入目前節(jié)點之后,節(jié)點數(shù)加1返回一個迭代器,指向新節(jié)點進行到這里說明沒有發(fā)現(xiàn)新節(jié)點產(chǎn)生新節(jié)點將新節(jié)點插入到鏈表的頭部,節(jié)點個數(shù)加1返回一個迭代器,指向新節(jié)點
}
10、hash functions
對于字符串,設(shè)計了一個轉(zhuǎn)換函數(shù)
inline size_t __stl_hash_string(const char* s)
{unsigned long h = 0; for ( ; *s; ++s)h = 5*h + *s;return size_t(h);
} 其他大部分hash functions什么也不做,只是返回原值。
轉(zhuǎn)載于:https://www.cnblogs.com/ruan875417/p/4558310.html
總結(jié)
以上是生活随笔為你收集整理的【STL源码剖析读书笔记】【第5章】关联式容器之hashtable的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下occi操作oracle数据
- 下一篇: pewell推子电池多少钱一个?