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那么T的类型就是pair<K,V>(V这个模板参数由上一层的map传进来的!)
如果我们封装的是set那么T的类型就是key的类型
Hash就是哈希函数的仿函数的用来让==key类型支持取模==(key类型不一定是整形,不是整形就不支持取模)
KeyofT是为了能够同时适应map与set的封装!——是一个仿函数!
==关于第四个模板类型存在的理由因为map的数据类型是pair<K,V>,如果里面的key在pair里面,而set的数据类型即使key!但是两者的用法不一样!==
//在map里面的data类型是pair<K,V> //里面的key是 data.first; //在set里面的data的类型是key //里面key就是 data; //为了能够让两者的在形式上统一,于是有了KeyofT这个仿函数! KeyofT()(data)//这样子皆可以自适应的根据data的类型去提取出相应的仿函数! //后面就可以等实现的时候就明白这个仿函数的重要作用
==其实还有一个仿函数——equal,用来支持等于的!因为有的key类型并不一定支持 = ===但是因为不怎么重要这里就实现了
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; }; }