赞
踩
1. unordered_map是存储<key, value>键值对的关联式容器,其允许通过keys快速的索引到与其对应的value。
2. 在unordered_map中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此
键关联。键和映射值的类型可能不同。
3. 在内部,unordered_map没有对<kye, value>按照任何特定的顺序排序, 为了能在常数范围内找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。
4. unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭代方面效率较低。
5. unordered_maps实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问
value。
6. 它的迭代器至少是前向迭代器。
函数声明 | 功能介绍 |
unordered_map | 构造不同格式的unordered_map对象 |
函数声明 | 功能介绍 |
bool empty() const | 检测unordered_map是否为空 |
size_t size() const | 获取unordered_map的有效元素个数 |
函数声明 | 功能介绍 |
begin | 返回unordered_map第一个元素的迭代器 |
end | 返回unordered_map最后一个元素下一个位置的迭代器 |
cbegin | 返回unordered_map第一个元素的const迭代器 |
cend | 返回unordered_map最后一个元素下一个位置的const迭代器 |
函数声明 | 功能介绍 |
operator[] | 返回与key对应的value,没有一个默认值 |
注意:该函数中实际调用哈希桶的插入操作,用参数key与V()构造一个默认值往底层哈希桶
中插入,如果key不在哈希桶中,插入成功,返回V(),插入失败,说明key已经在哈希桶中,
将key对应的value返回。
函数声明 | 功能介绍 |
iterator find(const K& key) | 返回key在哈希桶中的位置 |
size_t count(const K& key) | 返回哈希桶中关键码为key的键值对的个数 |
注意:unordered_map中key是不能重复的,因此count函数的返回值最大为1
函数声明 | 功能介绍 |
insert | 向容器中插入键值对 |
erase | 删除容器中的键值对 |
void clear() | 清空容器中有效元素个数 |
void swap(unordered_map&) | 交换两个容器中的元素 |
函数声明 | 功能介绍 |
size_t bucket_count()const | 返回哈希桶中桶的总个数 |
size_t bucket_size(size_t n)const | 返回n号桶中有效元素的总个数 |
size_t bucket(const K& key) | 返回元素key所在的桶号 |
set跟map及其相似,参照map使用即可。
- class Solution {
- public:
- int repeatedNTimes(vector<int>& nums) {
- int n = nums.size() / 2;
- //用unordered_map统计每个元素出现的次数
- unordered_map<int, int> m;
- for(auto e : nums)
- {
- m[e]++;
- }
- //找出出现次数为n的元素
- for(auto& e : m)
- {
- if(e.second == n)
- return e.first;
- }
- return -1;
- }
- };
- class Solution {
- public:
- vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
- //对nums1用unordered_set去重
- unordered_set<int> s1;
- for(auto e : nums1)
- s1.insert(e);
- //对nums2用unordered_set去重
- unordered_set<int> s2;
- for(auto e : nums2)
- s2.insert(e);
- //遍历s1找出与s2中相同的元素
- vector<int> v;
- for(auto e : s1)
- {
- if(s2.find(e) != s2.end())
- v.push_back(e);
- }
- return v;
- }
- };
顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(logN),搜索的效率取决于搜索过程中元素的比较次数。
理想的搜索方法:可以不经过任何比较,一次直接从表中得到要搜索的元素。
如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素
当向该结构:
插入元素
根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放。
搜索元素
对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置
取元素比较,若关键码相等,则搜索成功。
该方式即为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称
为哈希表(Hash Table)(或者称散列表)
不同关键字通过相同哈希函数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。
把具有不同关键码而具有相同哈希地址的数据元素称为“同义词”。
引起哈希冲突的一个原因可能是:哈希函数设计不够合理。
哈希函数设计原则:
1.哈希函数的定义域必须包括需要存储的全部关键码,而如果散列表允许有m个地址时,其值域必须在0到m-1之间
2.哈希函数计算出来的地址能均匀分布在整个空间中
3.哈希函数应该比较简单
常见哈希函数:
1.直接定址法(常用)
2.除留余数法(常用)
3.平方取中法
4.折叠法
5.随机数法
6.数学分析法
闭散列是用的线性探测的方法实现,线性探测
线性探测优点:实现非常简单,
线性探测缺点:一旦发生哈希冲突,所有的冲突连在一起,容易产生数据“堆积”,即:不同
关键码占据了可利用的空位置,使得寻找某关键码的位置需要许多次比较,导致搜索效率降
低。
如何更好的缓解这种情况?
可以进行二次探测
- #include<vector>
-
- template<class K>
- struct HashFunc
- {
- size_t operator()(const K& key)
- {
- return (size_t)key;
- }
- };
-
- //特化
- template<>
- struct HashFunc<string>
- {
- size_t operator()(const string& key)
- {
- size_t hash = 0;
- for (auto ch : key)
- {
- hash *= 131;
- hash += ch;
- }
- return hash;
- }
- };
-
- //开放地址寻址
- namespace open_adress
- {
- enum State
- {
- EMPTY,
- EXIST,
- DELETE
- };
- template<class K, class V>
- struct HashData
- {
- pair<K, V> _kv;
- State _state = EMPTY;
- };
-
-
-
- template<class K, class V, class Hash = HashFunc<K>>
- class HashTable
- {
- public:
- HashTable()
- {
- _tables.resize(10);
- }
- bool Insert(const pair<K, V>& kv)
- {
-
- if (_n * 10 / _tables.size() >= 7)
- {
- //扩容
-
- HashTable<K, V, Hash> newHT;
- newHT._tables.resize(_tables.size() * 2);
-
- for (size_t i = 0; i < _tables.size(); i++)
- {
- if (_tables[i]._state == EXIST)
- {
- newHT.Insert(_tables[i]._kv);
- }
- }
- _tables.swap(newHT._tables);
- }
- Hash hs;
- size_t hashi = hs(kv.first) % _tables.size();
-
- //线性探测
- while (_tables[hashi]._state == EXIST)
- {
- ++hashi;
- hashi %= _tables.size();
- }
- _tables[hashi]._kv = kv;
- _tables[hashi]._state = EXIST;
- _n++;
- return true;
- }
- HashData<K, V>* Find(const K& key)
- {
- Hash hs;
- size_t hashi = hs(key) % _tables.size();
- while (_tables[hashi]._state != EMPTY)
- {
- if (_tables[hashi]._state == EXIST &&
- _tables[hashi]._kv.first == key)
- {
- return &_tables[hashi];
- }
- ++hashi;
- hashi %= _tables.size();
- }
-
- return nullptr;
- }
- bool Erase(const K& key)
- {
- HashData<K, V>* ret = Find(key);
- if (ret != nullptr)
- {
- ret->_state = EMPTY;
- _n--;
-
- return true;
- }
- else
- {
- return false;
- }
- }
- private:
- vector<HashData<K, V>> _tables;
- size_t _n = 0; //有效数据个数
- };
-
- void testHT1()
- {
- int a[] = { 12, 33434, 223 ,3 };
- HashTable<int, int> ht;
-
- for (auto e : a)
- {
- ht.Insert(make_pair(e, e));
- }
-
- cout << ht.Find(12) << endl;
- cout << ht.Find(223) << endl;
-
- ht.Erase(223);
-
- cout << ht.Find(12) << endl;
- cout << ht.Find(223) << endl;
- }
- void testHT2()
- {
- HashTable<string, int> ht;
-
- ht.Insert(make_pair("sort", 1));
- ht.Insert(make_pair("left", 2));
- ht.Insert(make_pair("right", 3));
- ht.Insert(make_pair("ok", 4));
- }
- }
闭散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷。
开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地
址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链
接起来,各链表的头结点存储在哈希表中。
- //哈希桶法
- namespace hash_bucket
- {
- template<class T>
- struct HashNode
- {
- T _data;
- HashNode<T>* next;
-
- HashNode(const T& data)
- :_data(data)
- ,next(nullptr)
- {}
- };
-
- 前置声明
- //template<class K, class T, class KeyOfT, class Hash>
- //class HashTable;
-
- //template<class K, class T, class KeyOfT, class Hash>
- //struct __HTIterator
- //{
- // typedef HashNode<T> Node;
- // typedef __HTIterator Self;
-
- // Node* _node;
- // HashTable<K, T, KeyOfT, Hash>* _pht;
-
- // __HTIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht)
- // :_node(node)
- // ,_pht(pht)
- // {}
-
- // Self& operator++()
- // {
- // if (_node->next)
- // {
- // //当前桶没走完,找当前桶的下一个节点
- // _node = _node->next;
- // }
- // else
- // {
- // //当前桶走完了,找下一个不为空的桶的第一个节点
- // KeyOfT kot;
- // Hash hs;
- // size_t i = hs(kot(_node->_data)) % _pht->_tables.size();
- // ++i;
- // for (; i < _pht->_tables.size(); i++)
- // {
- // if (_pht->_tables)
- // break;
- // }
-
- // if (i == _pht->_tables.size())
- // {
- // //所有桶都走完了,最后一个的下一个用nullptr标记
- // _node = nullptr;
- // }
- // else
- // {
- // _node = _pht->_tables[i];
- // }
- // }
- // return *this;
- // }
-
- // bool operator!=(const Self& s)
- // {
- // return _node != s._node;
- // }
- //};
-
- template<class K, class T, class KeyOfT, class Hash>
- class HashTable
- {
- typedef HashNode<T> Node;
- public:
-
-
- 友元声明
- //template<class K, class T, class KeyOfT, class Hash>
- //friend class HashTable;
-
- template<class Ptr, class Ref>
- struct __HTIterator
- {
- typedef HashNode<T> Node;
- typedef __HTIterator Self;
-
- Node* _node;
- HashTable* _pht;
-
- __HTIterator(Node* node, HashTable* pht)
- :_node(node)
- , _pht(pht)
- {}
- Ref operator*()
- {
- return _node->_data;
- }
- Ptr operator->()
- {
- return &_node->_data;
- }
- Self& operator++()
- {
- if (_node->next)
- {
- //当前桶没走完,找当前桶的下一个节点
- _node = _node->next;
- }
- else
- {
- //当前桶走完了,找下一个不为空的桶的第一个节点
- KeyOfT kot;
- Hash hs;
- size_t i = hs(kot(_node->_data)) % _pht->_tables.size();
- ++i;
- for (; i < _pht->_tables.size(); i++)
- {
- if (_pht->_tables[i])
- break;
- }
-
- if (i == _pht->_tables.size())
- {
- //所有桶都走完了,最后一个的下一个用nullptr标记
- _node = nullptr;
- }
- else
- {
- _node = _pht->_tables[i];
- }
- }
- return *this;
- }
-
- bool operator!=(const Self& s)
- {
- return _node != s._node;
- }
- };
- typedef __HTIterator<T*, T&> iterator;
- typedef __HTIterator<const T*, const T&> const_iterator;
- iterator begin()
- {
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
- if (cur)
- {
- //this --> HashTable*
- return iterator(cur, this);
- }
- }
- return end();
- }
- iterator end()
- {
- return iterator(nullptr, this);
- }
- const_iterator begin() const
- {
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
- if (cur)
- {
- //this --> HashTable*
- return const_iterator(cur, this);
- }
- }
- return end();
- }
- const_iterator end() const
- {
- return const_iterator(nullptr, this);
- }
- HashTable()
- {
- _tables.resize(10, nullptr);
- _n = 0;
- }
- ~HashTable()
- {
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
-
- while (cur)
- {
- Node* next = cur->next;
- delete cur;
- cur = next;
- }
- _tables[i] = nullptr;
- }
- }
-
- pair<iterator, bool> Insert(const T& data)
- {
- Hash hs;
- KeyOfT kot;
- iterator it = Find(kot(data));
- if (it != end())
- return make_pair(it, false);
- //扩容
- //负载因子为1时需要扩容
- if (_n == _tables.size())
- {
- vector<Node*> newTables(_tables.size() * 2, nullptr);
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
- while (cur)
- {
- Node* next = cur->next;
- //头插新表的位置
- size_t hashi = hs(kot(cur->_data)) % newTables.size();
- cur->next = newTables[hashi];
- newTables[hashi] = cur;
-
- cur = next;
- }
- }
- _tables.swap(newTables);
- }
-
-
- size_t hashi = hs(kot(data)) % _tables.size();
-
- //头插
- Node* newnode = new Node(data);
- newnode->next = _tables[hashi];
- _tables[hashi] = newnode;
-
- ++_n;
- return make_pair(iterator(newnode, this), true);
- }
- iterator Find(const K& key)
- {
- Hash hs;
- KeyOfT kot;
- size_t hashi = hs(key) % _tables.size();
- Node* cur = _tables[hashi];
- while (cur)
- {
- if (kot(cur->_data) == key)
- {
- return iterator(cur, this);
- }
- cur = cur->next;
- }
- return end();
- }
- bool Erase(const K& key)
- {
- Hash hs;
- KeyOfT kot;
- size_t hashi = hs(key) % _tables.size();
- Node* prev = nullptr;
- Node* cur = _tables[hashi];
- while (cur)
- {
- if (kot(cur->_data) == key)
- {
- //删除的是第一个
- if (prev == nullptr)
- {
- _tables[hashi] = cur->next;
- }
- else
- {
- prev->next = cur->next;
- }
- delete cur;
-
- return true;
- }
- else
- {
- prev = cur;
- cur = cur->next;
- }
- }
- return false;
- }
- private:
- vector<Node*> _tables;
- size_t _n;
- };
- }
应用链地址法处理溢出,需要增设链接指针,似乎增加了存储开销。事实上:
由于开地址法必须保持大量的空闲空间以确保搜索效率,如二次探查法要求装载因子a <=
0.7,而表项所占空间又比指针大的多,所以使用链地址法反而比开地址法节省存储空间。
- #pragma once
-
- namespace bit
- {
- template<class K, class V, class Hash = HashFunc<K>>
- class unordered_map
- {
- struct MapKeyOfT
- {
- const K& operator()(const pair<K, V>& kv)
- {
- return kv.first;
- }
- };
- public:
- typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::iterator iterator;
- typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::const_iterator const_iterator;
-
- iterator begin()
- {
- return _ht.begin();
- }
- iterator end()
- {
- return _ht.end();
- }
- const_iterator begin() const
- {
- return _ht.begin();
- }
- const_iterator end() const
- {
- return _ht.end();
- }
- pair<iterator, bool> insert(const pair<K, V>& kv)
- {
- return _ht.Insert(kv);
- }
- bool Erase(const K& key)
- {
- return _ht.Erase(key);
- }
- V& operator[](const K& key)
- {
- pair<iterator, bool> ret = insert(make_pair(key, V()));
- return ret.first->second;
- }
- private:
- hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;
- };
- void test_unordered_map()
- {
- string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
- "苹果", "香蕉", "苹果", "香蕉","苹果","草莓", "苹果","草莓" };
- unordered_map<string, int> countMap;
- for (auto& e : arr)
- {
- countMap[e]++;
- }
-
- unordered_map<string, int>::iterator it = countMap.begin();
- while (it != countMap.end())
- {
- //it->first += 'x'; // key不能修改
- it->second += 1; // value可以修改
- cout << it->first << ":" << it->second << endl;
- ++it;
- }
- cout << endl;
-
- for (auto& kv : countMap)
- {
- cout << kv.first << ":" << kv.second << endl;
- }
- cout << endl;
- }
- }
- #pragma once
-
- namespace bit
- {
- template<class K, class Hash = HashFunc<K>>
- class unordered_set
- {
- struct SetKeyOfT
- {
- const K& operator()(const K& key)
- {
- return key;
- }
- };
- public:
- typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::iterator iterator;
- typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::const_iterator const_iterator;
-
- iterator begin()
- {
- return _ht.begin();
- }
- iterator end()
- {
- return _ht.end();
- }
- const_iterator begin() const
- {
- return _ht.begin();
- }
- const_iterator end() const
- {
- return _ht.end();
- }
- pair<iterator, bool> insert(const K& key)
- {
- return _ht.Insert(key);
- }
- bool Erase(const K& key)
- {
- return _ht.Erase(key);
- }
- private:
- hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;
- };
- }
- #pragma once
- #include<vector>
-
- template<class K>
- struct HashFunc
- {
- size_t operator()(const K& key)
- {
- return (size_t)key;
- }
- };
-
- //特化
- template<>
- struct HashFunc<string>
- {
- size_t operator()(const string& key)
- {
- size_t hash = 0;
- for (auto ch : key)
- {
- hash *= 131;
- hash += ch;
- }
- return hash;
- }
- };
-
- //开放地址寻址
- namespace open_adress
- {
- enum State
- {
- EMPTY,
- EXIST,
- DELETE
- };
- template<class K, class V>
- struct HashData
- {
- pair<K, V> _kv;
- State _state = EMPTY;
- };
-
-
-
- template<class K, class V, class Hash = HashFunc<K>>
- class HashTable
- {
- public:
- HashTable()
- {
- _tables.resize(10);
- }
- bool Insert(const pair<K, V>& kv)
- {
-
- if (_n * 10 / _tables.size() >= 7)
- {
- //扩容
-
- HashTable<K, V, Hash> newHT;
- newHT._tables.resize(_tables.size() * 2);
-
- for (size_t i = 0; i < _tables.size(); i++)
- {
- if (_tables[i]._state == EXIST)
- {
- newHT.Insert(_tables[i]._kv);
- }
- }
- _tables.swap(newHT._tables);
- }
- Hash hs;
- size_t hashi = hs(kv.first) % _tables.size();
-
- //线性探测
- while (_tables[hashi]._state == EXIST)
- {
- ++hashi;
- hashi %= _tables.size();
- }
- _tables[hashi]._kv = kv;
- _tables[hashi]._state = EXIST;
- _n++;
- return true;
- }
- HashData<K, V>* Find(const K& key)
- {
- Hash hs;
- size_t hashi = hs(key) % _tables.size();
- while (_tables[hashi]._state != EMPTY)
- {
- if (_tables[hashi]._state == EXIST &&
- _tables[hashi]._kv.first == key)
- {
- return &_tables[hashi];
- }
- ++hashi;
- hashi %= _tables.size();
- }
-
- return nullptr;
- }
- bool Erase(const K& key)
- {
- HashData<K, V>* ret = Find(key);
- if (ret != nullptr)
- {
- ret->_state = EMPTY;
- _n--;
-
- return true;
- }
- else
- {
- return false;
- }
- }
- private:
- vector<HashData<K, V>> _tables;
- size_t _n = 0; //有效数据个数
- };
-
- void testHT1()
- {
- int a[] = { 12, 33434, 223 ,3 };
- HashTable<int, int> ht;
-
- for (auto e : a)
- {
- ht.Insert(make_pair(e, e));
- }
-
- cout << ht.Find(12) << endl;
- cout << ht.Find(223) << endl;
-
- ht.Erase(223);
-
- cout << ht.Find(12) << endl;
- cout << ht.Find(223) << endl;
- }
- void testHT2()
- {
- HashTable<string, int> ht;
-
- ht.Insert(make_pair("sort", 1));
- ht.Insert(make_pair("left", 2));
- ht.Insert(make_pair("right", 3));
- ht.Insert(make_pair("ok", 4));
- }
- }
-
- //哈希桶法
- namespace hash_bucket
- {
- template<class T>
- struct HashNode
- {
- T _data;
- HashNode<T>* next;
-
- HashNode(const T& data)
- :_data(data)
- ,next(nullptr)
- {}
- };
-
- 前置声明
- //template<class K, class T, class KeyOfT, class Hash>
- //class HashTable;
-
- //template<class K, class T, class KeyOfT, class Hash>
- //struct __HTIterator
- //{
- // typedef HashNode<T> Node;
- // typedef __HTIterator Self;
-
- // Node* _node;
- // HashTable<K, T, KeyOfT, Hash>* _pht;
-
- // __HTIterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht)
- // :_node(node)
- // ,_pht(pht)
- // {}
-
- // Self& operator++()
- // {
- // if (_node->next)
- // {
- // //当前桶没走完,找当前桶的下一个节点
- // _node = _node->next;
- // }
- // else
- // {
- // //当前桶走完了,找下一个不为空的桶的第一个节点
- // KeyOfT kot;
- // Hash hs;
- // size_t i = hs(kot(_node->_data)) % _pht->_tables.size();
- // ++i;
- // for (; i < _pht->_tables.size(); i++)
- // {
- // if (_pht->_tables)
- // break;
- // }
-
- // if (i == _pht->_tables.size())
- // {
- // //所有桶都走完了,最后一个的下一个用nullptr标记
- // _node = nullptr;
- // }
- // else
- // {
- // _node = _pht->_tables[i];
- // }
- // }
- // return *this;
- // }
-
- // bool operator!=(const Self& s)
- // {
- // return _node != s._node;
- // }
- //};
-
- template<class K, class T, class KeyOfT, class Hash>
- class HashTable
- {
- typedef HashNode<T> Node;
- public:
-
-
- 友元声明
- //template<class K, class T, class KeyOfT, class Hash>
- //friend class HashTable;
-
- template<class Ptr, class Ref>
- struct __HTIterator
- {
- typedef HashNode<T> Node;
- typedef __HTIterator Self;
-
- Node* _node;
- HashTable* _pht;
-
- __HTIterator(Node* node, HashTable* pht)
- :_node(node)
- , _pht(pht)
- {}
- Ref operator*()
- {
- return _node->_data;
- }
- Ptr operator->()
- {
- return &_node->_data;
- }
- Self& operator++()
- {
- if (_node->next)
- {
- //当前桶没走完,找当前桶的下一个节点
- _node = _node->next;
- }
- else
- {
- //当前桶走完了,找下一个不为空的桶的第一个节点
- KeyOfT kot;
- Hash hs;
- size_t i = hs(kot(_node->_data)) % _pht->_tables.size();
- ++i;
- for (; i < _pht->_tables.size(); i++)
- {
- if (_pht->_tables[i])
- break;
- }
-
- if (i == _pht->_tables.size())
- {
- //所有桶都走完了,最后一个的下一个用nullptr标记
- _node = nullptr;
- }
- else
- {
- _node = _pht->_tables[i];
- }
- }
- return *this;
- }
-
- bool operator!=(const Self& s)
- {
- return _node != s._node;
- }
- };
- typedef __HTIterator<T*, T&> iterator;
- typedef __HTIterator<const T*, const T&> const_iterator;
- iterator begin()
- {
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
- if (cur)
- {
- //this --> HashTable*
- return iterator(cur, this);
- }
- }
- return end();
- }
- iterator end()
- {
- return iterator(nullptr, this);
- }
- const_iterator begin() const
- {
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
- if (cur)
- {
- //this --> HashTable*
- return const_iterator(cur, this);
- }
- }
- return end();
- }
- const_iterator end() const
- {
- return const_iterator(nullptr, this);
- }
- HashTable()
- {
- _tables.resize(10, nullptr);
- _n = 0;
- }
- ~HashTable()
- {
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
-
- while (cur)
- {
- Node* next = cur->next;
- delete cur;
- cur = next;
- }
- _tables[i] = nullptr;
- }
- }
-
- pair<iterator, bool> Insert(const T& data)
- {
- Hash hs;
- KeyOfT kot;
- iterator it = Find(kot(data));
- if (it != end())
- return make_pair(it, false);
- //扩容
- //负载因子为1时需要扩容
- if (_n == _tables.size())
- {
- vector<Node*> newTables(_tables.size() * 2, nullptr);
- for (size_t i = 0; i < _tables.size(); i++)
- {
- Node* cur = _tables[i];
- while (cur)
- {
- Node* next = cur->next;
- //头插新表的位置
- size_t hashi = hs(kot(cur->_data)) % newTables.size();
- cur->next = newTables[hashi];
- newTables[hashi] = cur;
-
- cur = next;
- }
- }
- _tables.swap(newTables);
- }
-
-
- size_t hashi = hs(kot(data)) % _tables.size();
-
- //头插
- Node* newnode = new Node(data);
- newnode->next = _tables[hashi];
- _tables[hashi] = newnode;
-
- ++_n;
- return make_pair(iterator(newnode, this), true);
- }
- iterator Find(const K& key)
- {
- Hash hs;
- KeyOfT kot;
- size_t hashi = hs(key) % _tables.size();
- Node* cur = _tables[hashi];
- while (cur)
- {
- if (kot(cur->_data) == key)
- {
- return iterator(cur, this);
- }
- cur = cur->next;
- }
- return end();
- }
- bool Erase(const K& key)
- {
- Hash hs;
- KeyOfT kot;
- size_t hashi = hs(key) % _tables.size();
- Node* prev = nullptr;
- Node* cur = _tables[hashi];
- while (cur)
- {
- if (kot(cur->_data) == key)
- {
- //删除的是第一个
- if (prev == nullptr)
- {
- _tables[hashi] = cur->next;
- }
- else
- {
- prev->next = cur->next;
- }
- delete cur;
-
- return true;
- }
- else
- {
- prev = cur;
- cur = cur->next;
- }
- }
- return false;
- }
- private:
- vector<Node*> _tables;
- size_t _n;
- };
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。