1、前言:
前面我们利用红黑树封装了map(set),其存储的数据一般是有序的,今天我们封装unordered容器,实现无序的unordered_map(set)。
2、原理:
利用哈希表中的哈希桶实现其底层
3、步骤:
(1)进一步封装已完成的HashTable,实现KeyOfT来区别map(pair<K,V>)和set(K)传入的数据类型;
(2)实现迭代器iterator
(3) 实现无法修改的迭代器const_iterator
(4) 解决key的修改问题(map)
(5) 实现operator[](mao)
4、代码实现:
(1)keyoft:(利用T实现数据类型泛型判断map与set)
a、UnorderedMap
#pragma once
#include"HashTable.h"
namespace lhx
{
template<class K, class V>
class unordered_map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
bool insert(const pair<K, V>& kv)
{
return _ht.Insert(kv);
}
bool Find(const K& key)
{
return _ht.Find(key);
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT, Hash>_ht;
};
}
b、UnorderedSat:
#pragma once
#include"HashTable.h"
namespace lhx
{
template<class K>
class unordered_set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
bool insert(const K& key)
{
return _ht.Insert(key);
}
bool Find(const K& key)
{
return _ht.Find(key);
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, K, SetKeyOfT, Hash>_ht;
};
}
c、HashTable::hash_bucket:
#pragma once
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<map>
#include<vector>
#include<iostream>
using namespace std;
//除留余数法:
//缺点:发生哈希冲突,不同值取模后映射到同一位置
//解决:
//(1)闭散列
//(2)开散列
//并不是所有的类型均可以取模,所以我们应该实现仿函数进行整型转换来进行取模运算
//将仿函数放在类外以便两种方法一起使用
template<class K>
struct HashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
//string类型我们需要进行特化来解决不同字符串取模后具有相同的映射的问题
//特化
template<>
struct HashFunc<string>
{
size_t operator()(const string& key)
{
size_t hash = 0;
for (auto e : key)
{
hash *= 31;//实验表明31可以更好的区分
hash += e;
}
return hash;
}
};
//开散列:哈希桶/拉链法
//利用指针数组进行链接
namespace hash_bucket
{
template<class K, 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 = HashFunc<K>>
class HashTable
{
typedef HashNode<T> Node;
public:
HashTable()
{
_tables.resize(10, nullptr);
}
~HashTable()
{
//依次释放每个桶
for (int i = 0;i < _tables.size();i++)
{
Node* cur = _tables[i];
while (cur)
{
Node* next = cur->_next;
delete cur;
cur = next;
}
//全部释放完后指针数组节点置为空
_tables[i] = nullptr;
}
}
bool Insert(const T & data)
{
KeyOfT kot;//判断插入的数据是map还是set
Hash hs;
size_t hashi = hs(kot(data)) % _tables.size();
//载荷因子为一时扩容
if (_n == _tables.size())//(_n * 10 / _tables.size() >= 1)
{
//新开一个数组
vector<Node*> newtables(_tables.size() * 2, nullptr);
for (size_t i = 0; i < _tables.size(); i++)
{
//从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[i] = nullptr;
}
_tables.swap(newtables);
}
//头插
Node* newnode = new Node(data);
newnode->_next = _tables[hashi];
_tables[hashi] = newnode;
++_n;
return true;
}
Node* Find(const K& key)
{
KeyOfT kot;
Hash hs;
size_t hashi = hs(key) % _tables.size();
Node* cur = _tables[hashi];
while (cur)
{
if (kot(cur->_data) == key)
{
return cur;
}
cur = cur->_next;
}
return nullptr;
}
bool Erase(const K& key)
{
KeyOfT kot;
Hash hs;
size_t hashi = hs(key) % _tables.size();
Node* cur = _tables[hashi];
Node* prev = nullptr;
while (cur)
{
if (kot(cur->_data) == key)
{
if (prev == nullptr)
{
_tables[hashi] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
delete cur;
--_n;
return true;
}
prev = cur;
cur = cur->_next;
}
return false;
}
private:
vector<Node*>_tables;
size_t _n = 0;
};
}
(2)迭代器iterator:
为实现++我们需要将整个表传过来
HashTable::hash_bucket::Iterator
//迭代器
//前置声明解决相互依赖向上查找的问题
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;
Node* _node;
typedef HTIterator<K, T, KeyOfT, Hash> Self;
//哈希表的指针
HashTable< K, T, KeyOfT, Hash>* _pht;//向上查找哈希表
HTIterator(Node* node, HashTable< K, T, KeyOfT, Hash>* pht)
:_node(node)
,_pht(pht)
{}
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator ==(const Self& s)
{
return _node == s._node;
}
Self& operator++()
{
if (_node->_next)
{
//当前桶weizouwan
_node = _node->_next;
}
else
{
//当前桶走完找下一个
KeyOfT kot;
Hash hs;
//计算当前桶的位置
size_t hashi = hs(kot(_node->_data)) % _pht->_tables.size();
++hashi;//走完后先加加
while (hashi < _pht->_tables.size())
{
//下给位置桶不为空则循坏结束
if(_pht->_tables[hashi])
{
break;
}
hashi++;
}
if (hashi == _pht->_tables.size())
{
_node = nullptr;//相当于走到桶末End()
}
else
{
_node = _pht->_tables[hashi];
}
}
return *this;
}
};
HashTable::hash_bucket:
template<class K, class T, class KeyOfT,class Hash = HashFunc<K>>
class HashTable
{
typedef HashNode <T> Node;
typedef HTIterator< K, T, KeyOfT, Hash> Iterator;
//友元访问私有
template<class K, class T, class KeyOfT, class Hash >
friend struct HTIterator;
public:
Iterator Begin()
{
//表中没数据返回End()
if (_n == 0)
{
return End();
}
else
{
//有数据则找到第一个桶不为空的位置
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return Iterator(cur, this);
}
}
}
return End();
}
Iterator End()
{
return Iterator(nullptr, this);
}
......
private:
vector<Node*>_tables;
size_t _n = 0;
};
}
UnorderedMap:
#pragma once
#include"HashTable.h"
namespace lhx
{
template<class K, class V>
class unordered_map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename hash_bucket::HashTable<K, const K, MapKeyOfT>::Iterator iterator;
iterator begin()
{
return _ht.Begin();
}
iterator end()
{
return _ht.End();
}
bool insert(const pair<K, V>& kv)
{
return _ht.Insert(kv);
}
bool Find(const K& key)
{
return _ht.Find(key);
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT>_ht;
};
}
UnorderedSet:
#pragma once
#include"HashTable.h"
namespace lhx
{
template<class K>
class unordered_set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT>::Iterator iterator;
iterator begin()
{
return _ht.Begin();
}
iterator end()
{
return _ht.End();
}
bool insert(const K& key)
{
return _ht.Insert(key);
}
bool Find(const K& key)
{
return _ht.Find(key);
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, K, SetKeyOfT>_ht;
};
}
(3)const迭代器与key不修改:
HashTable::hash_bucket::Iterator:
//迭代器
//前置声明解决相互依赖向上查找的问题
template<class K, class T, class KeyOfT, class Hash >
class HashTable;
template<class K,class T,class Ref,class Ptr, class KeyOfT, class Hash >
struct HTIterator
{
typedef HashNode<T> Node;
Node* _node;
typedef HTIterator<K, T, Ref, Ptr,KeyOfT, Hash> Self;
//哈希表的指针
const HashTable< K, T, KeyOfT, Hash>* _pht;//向上查找哈希表
HTIterator(Node* node, const HashTable< K, T, KeyOfT, Hash>* pht)
:_node(node)
,_pht(pht)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator ==(const Self& s)
{
return _node == s._node;
}
Self& operator++()
{
if (_node->_next)
{
//当前桶weizouwan
_node = _node->_next;
}
else
{
//当前桶走完找下一个
KeyOfT kot;
Hash hs;
//计算当前桶的位置
size_t hashi = hs(kot(_node->_data)) % _pht->_tables.size();
++hashi;//走完后先加加
while (hashi < _pht->_tables.size())
{
//下给位置桶不为空则循坏结束
if(_pht->_tables[hashi])
{
break;
}
hashi++;
}
if (hashi == _pht->_tables.size())
{
_node = nullptr;//相当于走到桶末End()
}
else
{
_node = _pht->_tables[hashi];
}
}
return *this;
}
};
HashTable::hash_bucket:
template<class K, class T, class KeyOfT,class Hash = HashFunc<K>>
class HashTable
{
//友元访问私有
template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash >
friend struct HTIterator;
typedef HashNode <T> Node;
public:
typedef HTIterator< K, T, T&, T* ,KeyOfT, Hash> Iterator;
typedef HTIterator< K, T, const T&, const T*, KeyOfT, Hash> ConstIterator;
。。。。。。
private:
vector<Node*>_tables;
size_t _n = 0;
};
}
UnorderedMap:
#pragma once
#include"HashTable.h"
namespace lhx
{
template<class K, class V>
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>::Iterator iterator;
typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT>::ConstIterator 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();
}
bool insert(const pair<K, V>& kv)
{
return _ht.Insert(kv);
}
bool Find(const K& key)
{
return _ht.Find(key);
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT>_ht;
};
}
UnorderedSet:
#pragma once
#include"HashTable.h"
namespace lhx
{
template<class K>
class unordered_set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT>::Iterator iterator;
typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT>::ConstIterator 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();
}
bool insert(const K& key)
{
return _ht.Insert(key);
}
bool Find(const K& key)
{
return _ht.Find(key);
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, const K, SetKeyOfT>_ht;
};
}
(4)operator[]:(map)
HashTable::hash_bucket:
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 Ref, class Ptr, class KeyOfT, class Hash >
friend struct HTIterator;
typedef HashNode <T> Node;
public:
typedef HTIterator< K, T, T&, T* ,KeyOfT, Hash> Iterator;
typedef HTIterator< K, T, const T&, const T*, KeyOfT, Hash> ConstIterator;
......
pair<Iterator,bool> Insert(const T & data)
{
KeyOfT kot;//判断插入的数据是map还是set
Iterator it = Find(kot(data));
if (it != End())
return make_pair(it, false);
Hash hs;
size_t hashi = hs(kot(data)) % _tables.size();
//载荷因子为一时扩容
if (_n == _tables.size())//(_n * 10 / _tables.size() >= 1)
{
//新开一个数组
vector<Node*> newtables(_tables.size() * 2, nullptr);
for (size_t i = 0; i < _tables.size(); i++)
{
//从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[i] = nullptr;
}
_tables.swap(newtables);
}
//头插
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)
{
KeyOfT kot;
Hash hs;
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();
}
.......
private:
vector<Node*>_tables;
size_t _n = 0;
};
}
UnorderedMap:
namespace lhx
{
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>::ConstIterator const_iterator;
.......
pair<iterator, bool> insert(const pair<const K, V>& kv)
{
return _ht.Insert(kv);
}
iterator Find(const K& key)
{
return _ht.Find(key);
}
V&operator[](const K& key)
{
pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
return ret.first->second;
}
.......
private:
hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT,Hash>_ht;
};
}
5、总代码:
HashTable.h:
#pragma once
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<map>
#include<vector>
#include<iostream>
using namespace std;
//除留余数法:
//缺点:发生哈希冲突,不同值取模后映射到同一位置
//解决:
//(1)闭散列
//(2)开散列
//并不是所有的类型均可以取模,所以我们应该实现仿函数进行整型转换来进行取模运算
//将仿函数放在类外以便两种方法一起使用
template<class K>
struct HashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
//string类型我们需要进行特化来解决不同字符串取模后具有相同的映射的问题
//特化
template<>
struct HashFunc<string>
{
size_t operator()(const string& key)
{
size_t hash = 0;
for (auto e : key)
{
hash *= 31;//实验表明31可以更好的区分
hash += e;
}
return hash;
}
};
//开散列:哈希桶/拉链法
//利用指针数组进行链接
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 Ref,class Ptr, class KeyOfT, class Hash >
struct HTIterator
{
typedef HashNode<T> Node;
Node* _node;
typedef HTIterator<K, T, Ref, Ptr,KeyOfT, Hash> Self;
//哈希表的指针
const HashTable< K, T, KeyOfT, Hash>* _pht;//向上查找哈希表
HTIterator(Node* node, const HashTable< K, T, KeyOfT, Hash>* pht)
:_node(node)
,_pht(pht)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
Self& operator++()
{
if (_node->_next)
{
//当前桶weizouwan
_node = _node->_next;
}
else
{
//当前桶走完找下一个
KeyOfT kot;
Hash hs;
//计算当前桶的位置
size_t hashi = hs(kot(_node->_data)) % _pht->_tables.size();
++hashi;//走完后先加加
while (hashi < _pht->_tables.size())
{
//下给位置桶不为空则循坏结束
if(_pht->_tables[hashi])
{
break;
}
hashi++;
}
if (hashi == _pht->_tables.size())
{
_node = nullptr;//相当于走到桶末End()
}
else
{
_node = _pht->_tables[hashi];
}
}
return *this;
}
};
template<class K, class T, class KeyOfT,class Hash >
class HashTable
{
//友元访问私有
template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash >
friend struct HTIterator;
typedef HashNode <T> Node;
public:
typedef HTIterator< K, T, T&, T* ,KeyOfT, Hash> Iterator;
typedef HTIterator< K, T, const T&, const T*, KeyOfT, Hash> ConstIterator;
Iterator Begin()
{
//表中没数据返回End()
if (_n == 0)
{
return End();
}
else
{
//有数据则找到第一个桶不为空的位置
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return Iterator(cur, this);
}
}
}
return End();
}
Iterator End()
{
return Iterator(nullptr, this);
}
ConstIterator Begin()const
{
//表中没数据返回End()
if (_n == 0)
{
return End();
}
else
{
//有数据则找到第一个桶不为空的位置
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
if (cur)
{
return ConstIterator (cur, this);
}
}
}
return End();
}
ConstIterator End()const
{
return ConstIterator(nullptr, this);
}
HashTable()
{
_tables.resize(10, nullptr);
}
~HashTable()
{
//依次释放每个桶
for (int 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)
{
KeyOfT kot;//判断插入的数据是map还是set
Iterator it = Find(kot(data));
if (it != End())
return make_pair(it, false);
Hash hs;
size_t hashi = hs(kot(data)) % _tables.size();
//载荷因子为一时扩容
if (_n == _tables.size())//(_n * 10 / _tables.size() >= 1)
{
/*HashTable<K, V> newHT;
newHT._tables.resize(_tables.size() * 2);
for (size_t i = 0; i < _tables.size(); i++)
{
Node* cur = _tables[i];
while(cur)
{
newHT.Insert(cur->_kv);
cur = cur->_next;
}
}
_tables.swap(newHT._tables);*/
//新开一个数组
vector<Node*> newtables(_tables.size() * 2, nullptr);
for (size_t i = 0; i < _tables.size(); i++)
{
//从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[i] = nullptr;
}
_tables.swap(newtables);
}
//头插
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)
{
KeyOfT kot;
Hash hs;
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)
{
KeyOfT kot;
Hash hs;
size_t hashi = hs(key) % _tables.size();
Node* cur = _tables[hashi];
Node* prev = nullptr;
while (cur)
{
if (kot(cur->_data) == key)
{
if (prev == nullptr)
{
_tables[hashi] = cur->_next;
}
else
{
prev->_next = cur->_next;
}
delete cur;
--_n;
return true;
}
prev = cur;
cur = cur->_next;
}
return false;
}
private:
vector<Node*>_tables;
size_t _n = 0;
};
}
UnorderedSet.h:
#pragma once
#include"HashTable.h"
namespace lhx
{
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>::ConstIterator 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);
}
iterator Find(const K& key)
{
return _ht.Find(key);
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, const K, SetKeyOfT,Hash>_ht;
};
void Print(const unordered_set<int>& s)
{
unordered_set<int>::const_iterator it = s.begin();
while (it != s.end())
{
// *it += 1;
cout << *it << " ";
++it;
}
cout << endl;
}
struct Date
{
int _year;
int _month;
int _day;
bool operator==(const Date& d) const
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
};
struct HashDate
{
size_t operator()(const Date& key)
{
// 112
// 121
return (key._year * 31 + key._month) * 31 + key._day;
}
};
void test_set()
{
unordered_set<int> s;
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14, 3,3,15 };
for (auto e : a)
{
s.insert(e);
}
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
unordered_set<int>::iterator it = s.begin();
while (it != s.end())
{
//*it += 1;
cout << *it << " ";
++it;
}
cout << endl;
unordered_set<Date, HashDate> us;
us.insert({ 2024, 7, 25 });
us.insert({ 2024, 7, 26 });
Print(s);
}
}
UnorderedMap:
#pragma once
#include"HashTable.h"
namespace lhx
{
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>::ConstIterator 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<const K, V>& kv)
{
return _ht.Insert(kv);
}
iterator Find(const K& key)
{
return _ht.Find(key);
}
V&operator[](const K& key)
{
pair<iterator, bool> ret = _ht.Insert(make_pair(key, V()));
return ret.first->second;
}
bool Erase(const K& key)
{
return _ht.Erase(key);
}
private:
hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT,Hash>_ht;
};
void test_map()
{
unordered_map<string, string> dict;
dict.insert({ "sort", "排序" });
dict.insert({ "left", "左边" });
dict.insert({ "right", "右边" });
dict["left"] = "左边,剩余";
dict["insert"] = "插入";
dict["string"];
unordered_map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
// 不能修改first,可以修改second
//it->first += 'x';
it->second += 'x';
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
}
}
test.cpp:
#define _CRT_SECURE_NO_WARNINGS
#include<unordered_set>
#include<unordered_map>
#include<set>
#include<iostream>
using namespace std;
//void test_set1()
//{
// unordered_set<int> s = { 3,1,6,7,8,2 };
// /*unordered_set<int>::iterator it = s.begin();
// while (it != s.end())
// {
// cout << *it << " ";
// ++it;
// }
// cout << endl;*/
//
// srand(time(0));
// for (size_t i = 0; i < 22000; ++i)
// {
// s.insert(rand()); // N比较大时,重复值比较多
// //v.push_back(rand()+i); // 重复值相对少
// //v.push_back(i); // 没有重复,有序
// }
//
// /*for (auto e : s)
// {
// cout << e << " ";
// }
// cout << endl;*/
//
// cout << s.bucket_count() << endl;
// //cout << s.max_bucket_count() << endl;
// cout << s.size() << endl;
// cout << "负载因子:" << s.load_factor() << endl;
// cout << "最大负载因子:" << s.max_load_factor() << endl;
//
// size_t len = 0;
// size_t nonEmptyBucketSize = 0;
// size_t maxLen = 0;
// for (size_t i = 0; i < s.bucket_count(); i++)
// {
// if (s.bucket_size(i) > 0)
// {
// if (s.bucket_size(i) > maxLen)
// maxLen = s.bucket_size(i);
//
// len += s.bucket_size(i);
// ++nonEmptyBucketSize;
// }
// }
// cout << "平均每个桶的长度:" << (double)len / nonEmptyBucketSize << endl;
// cout << "最大的桶的长度:" << maxLen << endl;
//}
//
//int test_set2()
//{
// const size_t N = 1000000;
//
// unordered_set<int> us;
// set<int> s;
//
// vector<int> v;
// v.reserve(N);
// srand(time(0));
// for (size_t i = 0; i < N; ++i)
// {
// //v.push_back(rand()); // N比较大时,重复值比较多
// v.push_back(rand() + i); // 重复值相对少
// //v.push_back(i); // 没有重复,有序
// }
//
// // 21:15
// size_t begin1 = clock();
// for (auto e : v)
// {
// s.insert(e);
// }
// size_t end1 = clock();
// cout << "set insert:" << end1 - begin1 << endl;
//
// size_t begin2 = clock();
// us.reserve(N);
// for (auto e : v)
// {
// us.insert(e);
// }
// size_t end2 = clock();
// cout << "unordered_set insert:" << end2 - begin2 << endl;
//
// int m1 = 0;
// size_t begin3 = clock();
// for (auto e : v)
// {
// auto ret = s.find(e);
// if (ret != s.end())
// {
// ++m1;
// }
// }
// size_t end3 = clock();
// cout << "set find:" << end3 - begin3 << "->" << m1 << endl;
//
// int m2 = 0;
// size_t begin4 = clock();
// for (auto e : v)
// {
// auto ret = us.find(e);
// if (ret != us.end())
// {
// ++m2;
// }
// }
// size_t end4 = clock();
// cout << "unorered_set find:" << end4 - begin4 << "->" << m2 << endl;
//
// cout << "插入数据个数:" << s.size() << endl;
// cout << "插入数据个数:" << us.size() << endl << endl;
//
// size_t begin5 = clock();
// for (auto e : v)
// {
// s.erase(e);
// }
// size_t end5 = clock();
// cout << "set erase:" << end5 - begin5 << endl;
//
// size_t begin6 = clock();
// for (auto e : v)
// {
// us.erase(e);
// }
// size_t end6 = clock();
// cout << "unordered_set erase:" << end6 - begin6 << endl << endl;
//
// return 0;
//}
//
//void test_map1()
//{
// unordered_map<string, string> dict;
// dict.insert({ "left", "左边" });
// dict["sort"];
// dict["sort"] = "排序";
//}
#include"HashTable.h"
#include"UnorderedSet.h"
#include"UnorderedMap.h"
int main()
{
//test_set2();
//test_map1();
/*hash_bucket::TestHT1();
hash_bucket::TestHT2();*/
//test_set2();
//bit::test_set();
lhx::test_map();
return 0;
}