【C++】Unordered_map/Unordered_map使用哈希表封装

目录

1. 整体学习的思维导图

2. 链地址法哈希表

3. 封装实现

3.1 解决key/pair问题

3.2 解决取key/pair.first问题

3.3 解决类型转换的问题

3.4 实现迭代器Iterator/const_Iterator

3.4.1 分析迭代器的++

3.5 实现map的operator[] 

4. 整体实现

4.1 HashTable.h

4.2 Myunordered_map.h 

4.3 Myunordered_set.h 


1. 整体学习的思维导图

【C++】Unordered_map/Unordered_map使用哈希表封装_第1张图片

2. 链地址法哈希表

本次的封装实现基于上次实现完成的链地址法的哈希表,以下是生成实现的整体代码,具体分析参考哈希表那章。

namespace Hashbucket
{
        // 
        template
        struct HashNode
        {
                pair _kv;
                HashNode* _next;
                
                HashNode(const pair& kv)
                        :_kv(kv)
                        ,_next(nullptr)
                {}
        };

        // 哈希表对象
        template
        class HashTable
        {
                typedef HashNode Node;
        public:

                HashTable()
                        :_tables(11)
                        ,_n(0)
                {}
                
                ~HashTable()
                {
                    for (size_t i = 0; i < _tables.size(); i++)
                    {
                            Node* cur = _tables[i];
                            while (cur)
                            {
                                    Node* next = cur->_next;
                                    delete cur;
                                    cur = next;
                            }
                            _tables[i] = nullptr;
                    }
                }
                
                HashTable(const HashTable& HT)
                    :_tables(HT._tables.size())
                {
                    for (size_t i = 0; i < HT._tables.size(); i++)
                    {
                        Node* cur = HT._tables[i];
                        while (cur)
                        {
                            Insert(cur->_kv);
                            cur = cur->_next;
                        }
                    }
                }
                
                HashTable& operator=(const HashTable& HT)
                {
                    if (this != &HT)
                    {
                        // 释放旧数据
                        for (size_t i = 0; i < _tables.size(); i++)
                        {
                            Node* cur = _tables[i];
                            while (cur)
                            {
                                Node* next = cur->_next;
                                delete cur;
                                cur = next;
                            }
                            _tables[i] = nullptr;
                        }
                
                        // 插入新数据
                        for (size_t i = 0; i < HT._tables.size(); i++)
                        {
                            Node* cur = HT._tables[i];
                            while (cur)
                            {
                                Insert(cur->_kv);
                                cur = cur->_next;
                            }
                        }
                    }
                    return *this;
                }
                
                bool Insert(const pair& kv)
                {                
                        if (Find(kv.first))
                                return false;
                        // 扩容
                        if (_n == _tables.size())
                        {
                                // 复用法
                                // 会创建新的节点+使用旧的节点
                                /*HashTable 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 newtables(_tables.size() * 2);
                                for (size_t i = 0; i < _tables.size(); i++)
                                {
                                        Node* cur = _tables[i];
                                        while (cur)
                                        {
                                                Node* next = cur->_next;
                                                // 重新计算出映射位置hashi
                                                size_t hashi = kv.first % newtables.size();
                                                cur->_next = newtables[hashi];
                                                newtables[hashi] = cur;
                                                cur = next;
                                        }
                                        _tables[i] = nullptr;
                                }
                                _tables.swap(newtables);
                        }

                        // 计算出映射位置hashi,这个计算必须在扩容下面不然映射会出错
                        size_t hashi = kv.first % _tables.size();
                        // 创建一个新的节点
                        Node* newnode = new Node(kv);
                        // 头插法
                        newnode->_next = _tables[hashi];  // 新节点指向原来的节点
                        _tables[hashi] = newnode;                 // 新节点成为新的头结点
                        ++_n;                                                        // ++节点数
                        return true;
                }

                Node* Find(const K& key)
                {
                        // 算出hashi
                        size_t hashi = key % _tables.size();
                        Node* cur = _tables[hashi];
                        while (cur)
                        {
                                if (cur->_kv.first == key)
                                        return cur;
                                cur = cur->_next;
                        }
                        return nullptr;
                }

                bool Erase(const K& key)
                {
                        // 算出hashi
                    

你可能感兴趣的:(C++的学习历程,c++,散列表,开发语言,哈希表)