STL源碼剖析(十八)關聯式容器之hash_map、hash_multimap
文章目錄
map 和 set 的區別就是,set 的 value 中 只有 key 沒有 data,而 map 的 value 既有 key 又有 data,每一個元素都是一個對組
一、hash_map、hash_multimap的數據結構
hash_map的定義如下
template <class Key, class T, class HashFcn = hash<Key>,
class EqualKey = equal_to<Key>,
class Alloc = alloc>
class hash_map
{
...
private:
typedef hashtable<pair<const Key, T>, Key, HashFcn,
select1st<pair<const Key, T> >, EqualKey, Alloc> ht;
ht rep;
...
};
它們的成員變量只有一個哈希表,下面解析一下哈希表的模板參數
哈希表的模板參數定義如下
template <class Value, class Key, class HashFcn,
class ExtractKey, class EqualKey,
class Alloc>
class hashtable {
...
};
-
Value:包含 key + data,hash_map 指定的是 pair<const Key, T>,一個對組,注意裏面的 key 是 const 類型,因爲 key 是不允許被修改的
-
Key:鍵值
-
HashFcn:哈希函數,hash_map 指定的是 hash<Key>,用於生成哈希值,這個上一篇文章已經講解過了,這裏不再講解
-
ExtractKey:從 value 中獲取 key,hash_map 的定義爲 select1st<pair<const Key, T> >,因爲每個元素都是 key 加 data,所以獲取鍵值就從對組中取出第一個元素就行,select1st 的定義如下
template <class Pair> struct select1st : public unary_function<Pair, typename Pair::first_type> { const typename Pair::first_type& operator()(const Pair& x) const { return x.first; } };
-
EqualKey:判斷 key 是否相等,hash_map 的定義爲 equal_to<Key> ,定義如下
template <class T> struct equal_to : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x == y; } };
hash_mulitmap 的數據結構和 hash_map 是一樣的,這裏不再列出
二、hash_map、hash_multimap的迭代器
hash_map 和 hash_multimap 的迭代器都是一樣的,定義如下
typedef typename ht::iterator iterator;
它們都是直接使用哈希表的迭代器
如果要修改對應的data,可以這樣做
it->second = xxx;
三、hash_map、hash_multimap的操作
hash_map 和 hash_multimap 的操作基本是相同的,只是插入元素的操作不同,這裏相同的部分只會列處 hash_map
3.1 構造函數
hash_map() : rep(100, hasher(), key_equal()) {}
初始化哈希表
3.2 析構函數
hash_map 和 hash_multimap 是沒有析構函數的,在釋放 hash_map 和 hash_multimap 對象的時候,會自動析構釋放成員變量,所以哈希表會被自動析構釋放
3.3 插入元素
hash_map 的 insert
pair<iterator, bool> insert(const value_type& obj)
{ return rep.insert_unique(obj); }
因爲不允許鍵值重複,所以調用的哈希表的 insert_unique 操作
hash_multimap 的 insert
iterator insert(const value_type& obj) { return rep.insert_equal(obj); }
允許鍵值重複,所以調用的哈希表的 insert_equal 操作
3.4 刪除元素
size_type erase(const key_type& key) {return rep.erase(key); }
通過調用哈希表的 erase 完成操作
3.5 其他操作
begin
iterator begin() { return rep.begin(); }
end
iterator end() { return rep.end(); }
find
iterator find(const key_type& key) { return rep.find(key); }
可以看到,絕大數操作都是轉而調用哈希表完成的