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;
           };
}

==一共有四个模板参数!==

  1. k就是key的类型!
  2. T==不是value的类型!==——是节点(Node)的存的数据的类型

例如我们如果封装的是map那么T的类型就是pair<K,V>(V这个模板参数由上一层的map传进来的!)

如果我们封装的是set那么T的类型就是key的类型

  1. Hash就是哈希函数的仿函数的用来让==key类型支持取模==(key类型不一定是整形,不是整形就不支持取模)

  2. 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库的早期实现中也确实采用了这个说法

image-20230427192138053

==我们可以看到因为每一次扩容如果要算下一个素数很麻烦!所以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表的迭代器是如何实现的!image-20230428142109591

我们可以看到里面是用了两个成员变量,一个是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));
               }
           };

}

image-20230429140011602

==当我们进行使用的时候就会出现报错!==

为什么会出现报错!——我们可以看到报错结果是出现了类型转换!——将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;
           };
}