unordered_set与unordered_map的模拟实现
哈希节点类
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class T>
struct HashNode
{
HashNode(const T& data = T())
:_data(data)
,_next(nullptr)
{}
T _data;
HashNode<T>* _next;
};
}
==之所以是一个T的模板参数因为我们不知道传过来的是一个pair还是一个key==
哈希桶成员变量
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
==一共有四个模板参数!==
- k就是key的类型!
- T==不是value的类型!==——是节点(Node)的存的数据的类型
map的成员变量
#include "hash_bucket.h"
namespace MySTL
{
template<class K>
struct HashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};//默认的哈希函数
template<class K,class V,class Hash = HashFunc<K>>
class unordered_map
{
struct mapKeyOfValue
{
const K& operator()(const std::pair<K,V>& kv)
{
return kv.first;
}
};
//这就是keyofT的实现!
private:
HashBucket<K,std::pair<const K,V>,Hash,mapKeyOfValue> _hash;
};
}
set的成员变量
#include "hash_bucket.h"
namespace MySTL
{
template<class K>
struct HashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
template<class K,class Hash = HashFunc<K>>
class unordered_set
{
struct setKeyOfValue
{
const K& operator()(const K& key)
{
return key;
}
};
private:
HashBucket<K,K,Hash,setKeyOfValue> _hash;
};
}
哈希桶的构造函数
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
public:
HashBucket(size_t n = 10)
:_n(0)
{
_Bucket.resize(n);
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
哈希桶的析构函数
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
public:
~HashBucket()
{
for(auto cur : _Bucket)
{
while(cur)
{
Node* next = cur->_next;
delete cur;
cur = next;
}
}
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
哈希桶的Find
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
public:
Node* Find(const K& key)
{
size_t hashi = Hash()(key) % _Bucket.size();
KeyofT kot;
Node* cur = _Bucket[hashi];
while(cur)
{
//KeyofT这个仿函数这时候就发挥作用了!因为我们不知道data究竟是什么类型!所以就不好写表达式!
//但是使用了仿函数之后表达式的形式就变得统一起来了!
if(kot(cur->_data)== key)
return cur;
cur = cur->_next;
}
return nullptr;
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
map的find
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class V,class Hash = mapHashFunc<K>>
class unordered_map
{
public:
Node* find(const K& key)
{
return _hash.Find(key);
}
private:
HashBucket<K,std::pair<const K,V>,Hash,mapKeyOfValue> _hash;
};
}
set的find
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class Hash = setHashFunc<K>>
class unordered_set
{
public:
//Find
Node* find(const K& key)
{
return _hash.Find(key);
}
private:
HashBucket<K,K,Hash,setKeyOfValue> _hash;
};
}
哈希桶的Insert
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
public:
bool Insert(const T& data)
{
KeyofT kot;
if(Find(kot(data)))
return false;
//Find的参数类型是K,而data的类型是T,所以要用kot(data)来转换一下
if(_n == _Bucket.size())
{
//将旧表的节点全部拿出来,然后重新插入到新表中
std::vector<Node*> newBucket;
newBucket.resize(__stl_next_prime(_Bucket.size()), nullptr);
for(int i = 0;i< _Bucket.size();i++)
{
Node* cur = _Bucket[i];
while(cur)
{
Node* next = cur->_next;
size_t hashi = Hash()(kot(cur->_data)) % newBucket.size();
//用kot(data)是因为这里是要用原来的key来计算新的hash值
//我们不知道data是一个什么样的类型,所以不能用data来计算hash值
//cur是新插入的节点!要进行头插!变成新的头结点
//nweBucket[hashi]是原来的头结点!要变成新的头结点的next
cur->_next = newBucket[hashi];
//不用担心第一次是空的,即使第一次是nullptr,也不会出错!
newBucket[hashi] = cur;//变成新的头结点
cur = next;
}
_Bucket[i] = nullptr;
}
_Bucket.swap(newBucket);
}
size_t hashi = Hash()(kot(data)) % _Bucket.size();
//要放在扩容之后,因为扩容之后,_Bucket.size()已经变了
//哈希桶和哈希表不一样!哈希桶不用担心哈希冲突,因为哈希桶的每个位置都是一个链表
//直接进行头插
Node* newhead = new Node(data);
newhead->_next = _Bucket[hashi];
_Bucket[hashi] = newhead;
++_n;
return true;
}
inline unsigned long __stl_next_prime(unsigned long n)
{
static const int __stl_num_primes = 28;
static const unsigned long __stl_prime_list[__stl_num_primes] =
{
53, 97, 193, 389, 769,
1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433,
1572869, 3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189, 805306457,
1610612741, 3221225473, 4294967291
};
for(int i = 0;i<__stl_num_primes;i++)
{
if(__stl_prime_list[i] > n)
{
return __stl_prime_list[i];
}
}
return __stl_prime_list[__stl_num_primes-1];
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
有一个说法,就是如果表的大小是一个素数,那么就可以在取模的时候让数据更加的分散
而在STL库的早期实现中也确实采用了这个说法
==我们可以看到因为每一次扩容如果要算下一个素数很麻烦!所以STL库干脆给了一个素数表!然后通过lower_bound每次去找到比n更大的素数然后返回,而到最后如果到最大值了,就不再进行扩容!而是返回最大值!==
==我们这里也模仿了STL库使用了素数进行扩大==
map的insert
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class V,class Hash = HashFunc<K>>
class unordered_map
{
struct mapKeyOfValue
{
const K& operator()(const std::pair<K,V>& kv)
{
return kv.first;
}
};
public:
bool insert(const std::pair<K,V>& kv)
{
return _hash.Insert(kv);
}
private:
HashBucket<K,std::pair<const K,V>,Hash,mapKeyOfValue> _hash;
};
}
set的Insert
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class Hash = HashFunc<K>>
class unordered_set
{
struct setKeyOfValue
{
const K& operator()(const K& key)
{
return key;
}
};
public:
bool insert(const K& key)
{
return _hash.Insert(key);
}
private:
HashBucket<K,K,Hash,setKeyOfValue> _hash;
};
}
哈希桶的Erase
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
public:
bool Erase(const K& key)
{
//开散列不能像闭散列一样Find然后删除!因为这是一个单链表!要找到前一个节点才能删除!
size_t hashi = Hash()(key) % _Bucket.size();
Node* cur = _Bucket[hashi];
Node* curprev = nullptr;
KeyofT kot;
while(cur)
{
//找到后开始准备删除
if(kot(cur->_data)== key)
{
if(cur == _Bucket[hashi]) //如果删除的是头结点!
{
_Bucket[hashi] = cur->_next;
}
else
{
curprev->_next = cur->_next;
}
delete cur;
_n--;
return true;
}
cur = cur->_next;
curprev = cur;
}
return false;
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
```
map的erase
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class V,class Hash = mapHashFunc<K>>
class unordered_map
{
public:
bool erase(const K& key)
{
return _hash.Erase(key);
}
private:
HashBucket<K,std::pair<const K,V>,Hash,mapKeyOfValue> _hash;
};
}
set的erase
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class Hash = setHashFunc<K>>
class unordered_set
{
public:
bool erase(const K& key)
{
return _hash.Erase(key);
}
private:
HashBucket<K,K,Hash,setKeyOfValue> _hash;
};
}
哈希桶的迭代器实现——重点
对于hash桶的迭代器我们应该怎么实现呢?我们可以先看看STL库中的hash表的迭代器是如何实现的!
我们可以看到里面是用了两个成员变量,一个是cur,一个是表的指针!
因为哈希表的底层是一个单链表!所以这个迭代器也是一个单向迭代器!——只需要支持operator++就可以!
==如何遍历哈希表,可以先遍历一个单链表!遇到空后就一直往后找,直到找到新的桶为止!==
也可以选择空间换时间!再组织一个链表!来存储数据!然后用迭代器来遍历这个链表也行!
成员变量
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
//声明一下,因为下面要用到
template<class K,class T,class Hash,class KeyofT>
class HashBucket;
//如果放在HashBucket类的下面就不用声明!
template<class K,class T,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _Bucket;//表的指针!
};
}
构造函数
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _HT;//表的指针!
__HTIterator(Node* node,Bucket* HT)//构造函数!
:_node(node)
,_HT(HT)
{}
};
}
operator++——重点
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket;//声明一下如果放再这个类的后面就无所谓!
template<class K,class T,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _Bucket;//表的指针!
Self& operator++()
{
if(_node->_next!= nullptr)
{
_node = _node->_next;
}
else //到了这里说明这桶已经遍历完毕了!
{
size_t hashi = Hash()(KeyofT()(_node->_data)) % _HT->_Bucket.size();//记住要让这个迭代器为hashBucket类的友元!或者提供一个共有的size接口!
//这个代码就是先用仿函数KeyOfT的匿名对象提取出Key值
//然后再使用Hash这个仿函数进行转换
//我们要直接从下一个桶开始算!
++hashi;
while(hashi < _HT->_Bucket.size())
{
if(_HT->_Bucket[hashi])//不为空,说明这个桶里面有数据
{
_node = _HT->_Bucket[hashi];
break;
}
else//为空,说明这个桶里面没有数据,继续往后找
{
++hashi;
}
}
if(hashi == _HT->_Bucket.size())//说明已经到了最后一个桶了
{
_node = nullptr;
}
}
return *this;
}
};
}
operator*
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket;//声明一下如果放再这个类的后面就无所谓!
template<class K,class T,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _Bucket;//表的指针!
T& operator*()
{
return _node->_data;
}
};
}
operator->
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket;//声明一下如果放再这个类的后面就无所谓!
template<class K,class T,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _Bucket;//表的指针!
T* operator->()
{
return &_node->_data;
}
};
}
operator==
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket;//声明一下如果放再这个类的后面就无所谓!
template<class K,class T,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _Bucket;//表的指针!
bool operator==(const Self& s)
{
return _node == s._node;
}
};
}
operator!=
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket;//声明一下如果放再这个类的后面就无所谓!
template<class K,class T,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _Bucket;//表的指针!
bool operator==(const Self& s)
{
return _node == s._node;
}
};
}
哈希桶的const迭代器——重点
==哈希表的const迭代器是不能复用普通的迭代器的!这是为什么?==
==我们可以试试看改造改造一下!==
namespace MySTL
{
template<class T>
struct HashNode
{
HashNode(const T& data = T())
:_data(data)
,_next(nullptr)
{}
T _data;
HashNode<T>* _next;
};
//声明一下,因为下面要用到
template<class K,class T,class Hash,class KeyofT>
class HashBucket;
//添加两个模板参数Ptr与Ref
template<class K,class T,class Ptr,class Ref,class Hash,class KeyofT>
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Ptr,Ref,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _HT;//表的指针!
__HTIterator(Node* node,Bucket* HT)
:_node(node)
,_HT(HT)
{}
Self& operator++()
{
//......
}
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;
}
};
}
==使用同一个迭代器进封装!==
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
template<class Key,class Type,class APTr,class ARef,class Hashfunc,class KeyofValue>
friend struct __HTIterator;
public:
//使用同一个迭代器进行封装!
typedef __HTIterator<K,T,T*,T&,Hash,KeyofT> iterator;
typedef __HTIterator<K,T,const T*,const T&,Hash,KeyofT> const_iterator;
iterator begin()
{
for(int i = 0;i< _Bucket.size();i++)
{
if(_Bucket[i])
return iterator(_Bucket[i], this);
}
return iterator(nullptr,this);
}
const_iterator cbegin()const
{
for(int i = 0;i< _Bucket.size();i++)
{
if(_Bucket[i])
return const_iterator(_Bucket[i], this);
}
return const_iterator(nullptr,this);
}
iterator end()
{
return iterator(nullptr,this);
}
const_iterator cend()const
{
return const_iterator(nullptr,this);
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
==用这个迭代器来实现一个map的const迭代器!==
namespace MySTL
{
template<class K,class V,class Hash = mapHashFunc<K>>
class unordered_map
{
struct mapKeyOfValue
{
const K& operator()(const std::pair<K,V>& kv)
{
return kv.first;
}
};
public:
typedef typename HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue>::iterator iterator;
typedef typename HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue>::const_iterator const_iterator;
iterator begin()
{
return _hash.begin();
}
const_iterator cbegin()const
{
return _hash.cbegin();
}
iterator end()
{
return _hash.end();
}
const_iterator cend()const
{
return _hash.cend();
}
iterator Find(const K& key)
{
return _hash.Find(key);
}
private:
HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue> _hash;
void testunorderedmap()
{
unordered_map<int,int> ump;
ump.insert(std::make_pair(1,1));
}
};
}
==当我们进行使用的时候就会出现报错!==
为什么会出现报错!——我们可以看到报错结果是出现了类型转换!——将const指针转为了普通指针!发生了权限放大!
==其实原因就是我们传入的this指针!当我们因为当我们想要去调用const迭代器的时候!说明此时this指针的类型必然是 ——const 类名* this==
==但是我们看迭代器的成员中关于哈希桶的指针是一个普通的指针!==
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Ptr,Ref,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
Bucket* _HT;//表的指针!
}
==这时候模板就无法完成实例化了!因为类型不匹配!const类型的指针是无法初始化普通指针的!==
所以要怎么办呢?答案是就是——重新写一个类!这个而这个类型的成员变量类型变为const
struct __HTIterator
{
typedef HashNode<T> Node;
typedef __HTIterator<K,T,Ptr,Ref,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
const Bucket* _HT;//将表的指针改为const Bucket*这个类型!
}
const迭代器的实现!
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
struct __Const__HTIterator
{
typedef HashNode<T> Node;
typedef __Const__HTIterator<K,T,Hash,KeyofT> Self;
typedef HashBucket <K,T,Hash,KeyofT> Bucket;
Node* _node;
const Bucket* _HT;//将指针修改为const!
__Const__HTIterator(Node* node,const Bucket* HT)
:_node(node)
,_HT(HT)
{}
Self& operator++()//这里不用加上const否则会导致_node无法修改!
{
if(_node->_next!= nullptr)
{
_node = _node->_next;
}
else //到了这里说明这桶已经遍历完毕了!
{
size_t hashi = Hash()(KeyofT()(_node->_data)) % _HT->_Bucket.size();
//这个代码就是先用仿函数KeyOfT的匿名对象提取出Key值
//然后再使用Hash这个仿函数进行转换
//我们要直接从下一个桶开始算!
++hashi;
while(hashi < _HT->_Bucket.size())
{
if(_HT->_Bucket[hashi])//不为空,说明这个桶里面有数据
{
_node = _HT->_Bucket[hashi];
break;
}
else//为空,说明这个桶里面没有数据,继续往后找
{
++hashi;
}
}
if(hashi == _HT->_Bucket.size())//说明已经到了最后一个桶了
{
_node = nullptr;
}
}
return *this;
}
//将* 与 ->的返回值加上const
const T& operator*()
{
return _node->_data;
}
const T* operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
};
}
哈希的begin/end
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
//因为在声明友元的时候!如果模板参数名称相同会导致!报错!
template<class Key,class Type,class Hashfunc,class KeyofValue>
friend struct __HTIterator;
template<class Key,class Type,class Hashfunc,class KeyofValue>
friend struct __Const__HTIterator;
typedef __HTIterator<K,T,Hash,KeyofT> iterator;
typedef __Const__HTIterator<K,T,Hash,KeyofT> const_iterator;
public:
iterator begin()
{
for(int i = 0;i< _Bucket.size();i++)
{
if(_Bucket[i])
return iterator(_Bucket[i], this);
}
//找打第一个不为空的位置
return iterator(nullptr,this);
//到这里说明没有!
}
const_iterator begin()const
{
for(int i = 0;i< _Bucket.size();i++)
{
if(_Bucket[i])
return const_iterator(_Bucket[i], this);//this就是当前的哈希桶
//找打第一个不为空的位置
}
return const_iterator(nullptr,this);
}
iterator end()
{
return iterator(nullptr,this);
}
const_iterator end()const
{
return const_iterator(nullptr,this);
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
map的begin/end
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class V,class Hash = mapHashFunc<K>>
class unordered_map
{
public:
typedef typename HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue>::iterator iterator;
typedef typename HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue>::const_iterator const_iterator;
iterator begin()
{
return _hash.begin();
}
const_iterator begin()const
{
return _hash.begin();
}
iterator end()
{
return _hash.end();
}
const_iterator end()const
{
return _hash.end();
}
private:
HashBucket<K,std::pair<const K,V>,Hash,mapKeyOfValue> _hash;
};
}
set的begin与end
#include "hash_bucket.h"
namespace MySTL
{
template<class K,class Hash = setHashFunc<K>>
class unordered_set
{
public:
typedef typename HashBucket<K,K,Hash,setKeyOfValue>::const_iterator iterator;
typedef typename HashBucket<K,std::pair<K,V>,Hash,setKeyOfValue>::const_iterator const_iterator;
//set的键值是不能被修改的!所以我们都用const迭代器来封装
iterator begin()
{
return _hash.begin();
}
const_iterator begin()const
{
return _hash.begin();
}
iterator end()
{
return _hash.end();
}
const_iterator end()const
{
return _hash.end();
}
private:
HashBucket<K,K,Hash,setKeyOfValue> _hash;
};
}
map的operator[]重载
哈希表insert改造
#pragma once
#include <iostream>
#include <vector>
namespace MySTL
{
template<class K,class T,class Hash,class KeyofT>
class HashBucket
{
typedef HashNode<T> Node;
template<class Key,class Type,class Hashfunc,class KeyofValue>
friend struct __HTIterator;
template<class Key,class Type,class Hashfunc,class KeyofValue>
friend struct __Const__HTIterator;
public:
typedef __HTIterator<K,T,Hash,KeyofT> iterator;
typedef __Const__HTIterator<K,T,Hash,KeyofT> const_iterator;
iterator Find(const K& key)//FInd这里也随便改造一下!
{
size_t hashi = Hash()(key) % _Bucket.size();
KeyofT kot;
Node* cur = _Bucket[hashi];
while(cur)
{
if(kot(cur->_data)== key)
return iterator(cur, this);
cur = cur->_next;
}
return end();
}
//将返回值改成pair
std::pair<iterator,bool> Insert(const T& data)
{
KeyofT kot;
iterator it = Find(kot(data));
if(it != end())
return std::make_pair(it,false);
//找到了就将找到的节点的迭代器和false构成的pair返回
if(_n == _Bucket.size())
{
std::vector<Node*> newBucket;
newBucket.resize(__stl_next_prime(_Bucket.size()), nullptr);
for(int i = 0;i< _Bucket.size();i++)
{
Node* cur = _Bucket[i];
while(cur)
{
Node* next = cur->_next;
size_t hashi = Hash()(kot(cur->_data)) % newBucket.size();
cur->_next = newBucket[hashi];
newBucket[hashi] = cur;
cur = next;
}
_Bucket[i] = nullptr;
}
_Bucket.swap(newBucket);
}
size_t hashi = Hash()(kot(data)) % _Bucket.size();
Node* newhead = new Node(data);
newhead->_next = _Bucket[hashi];
_Bucket[hashi] = newhead;
++_n;
return std::make_pair(iterator(newhead, this), true);
}
private:
std::vector<Node*> _Bucket;
size_t _n;
};
}
map insert改造
//map的Insert改造
#include "hash_bucket.h"
namespace MySTL
{
template<class K>
struct mapHashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
template<class K,class V,class Hash = mapHashFunc<K>>
class unordered_map
{
struct mapKeyOfValue
{
const K& operator()(const std::pair<K,V>& kv)
{
return kv.first;
}
};
public:
typedef typename HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue>::iterator iterator;
typedef typename HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue>::const_iterator const_iterator;
//将返回值也进行修改
std::pair<iterator,bool> insert(const std::pair<K,V>& kv)
{
return _hash.Insert(kv);
}
private:
HashBucket<K,std::pair<const K,V>,Hash,mapKeyOfValue> _hash;
};
}
set insert改造
//set的Insert改造
#include "hash_bucket.h"
namespace MySTL
{
template<class K>
struct setHashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
template<class K,class Hash = setHashFunc<K>>
class unordered_set
{
struct setKeyOfValue
{
const K& operator()(const K& key)
{
return key;
}
};
typedef typename HashBucket<K,std::pair<K,V>,Hash,setKeyOfValue>::iterator iterator;
typedef typename HashBucket<K,std::pair<K,V>,Hash,setKeyOfValue>::const_iterator const_iterator;
//修改一下返回值!
std::pair<iterator,bool> insert(const K& key)
{
return _hash.Insert(key);
}
private:
HashBucket<K,K,Hash,setKeyOfValue> _hash;
};
}
map的operator[]重载的实现
#include "hash_bucket.h"
namespace MySTL
{
template<class K>
struct mapHashFunc
{
size_t operator()(const K& key)
{
return (size_t)key;
}
};
template<class K,class V,class Hash = mapHashFunc<K>>
class unordered_map
{
struct mapKeyOfValue
{
const K& operator()(const std::pair<K,V>& kv)
{
return kv.first;
}
};
public:
typedef typename HashBucket<K,std::pair<K,V>,Hash,mapKeyOfValue>::iterator iterator;
//这样就完成了对于[]的重装!
V& operator[](const K& key)
{
std::pair<iterator,bool> ret = _hash.Insert(make_pair(key,V()));
return ret.first->second;
//->已经被重装所以等价于下面
//return ret.first._node->_data.second;
}
private:
HashBucket<K,std::pair<const K,V>,Hash,mapKeyOfValue> _hash;
};
}