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