C++深入探究哈希表如何封装出unordered_set和unordered_map

哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方,说起来可能感觉有点复杂,我想我举个例子你就会明白了,最典型的的例子就是字典

默认你已经实现了哈希表(开散列)

封装前的哈希代码

namespace HashBucket
{
	template<class K,class V>
	struct HashNode
	{
		pair<K, V> _kv;
		HashNode* _next;
		HashNode(const pair<K, V>& kv)
			:_kv(kv)
			, _next(nullptr)
		{}
	};
	template<class K,class V,class Hash=HashFunc<K>>
	class HashTable
	{
		typedef HashNode<K,V> Node;
	public:
		Node* Find(const K& key)//Find函数返回值一般都是指针,通过指针访问这个自定义类型的成员
		{
			Hash hash;
			if (_tables.size() == 0)//表的大小为0,防止取余0
			{
				return nullptr;
			}
			size_t index = hash(key) % _tables.size();//找到桶号
			Node* cur = _tables[index];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					return cur;
				}
				else
				{
					cur = cur->_next;
				}
			}
			return nullptr;
		}
		size_t GetNextPrime(size_t prime)
		{
			const int PRIMECOUNT = 28;
			static const size_t primeList[PRIMECOUNT] =
			{
				53ul, 97ul, 193ul, 389ul, 769ul,
				1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
				49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
				1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
				50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
				1610612741ul, 3221225473ul, 4294967291ul
			};
			//ul表示unsigned long
			size_t i = 0;
			for (; i < PRIMECOUNT; ++i)
			{
				if (primeList[i] > prime)
					return primeList[i];
			}
			return primeList[i];
		}
		bool Insert(const pair<K, V>& kv)
		{
			if (Find(kv.first))//有相同的key直接返回false
			{
				return false;
			}
			//if(_n==0||_n==_tables.size())
			Hash hash;
			if (_n == _tables.size())//最开始_n为0,而_tables.size()也为0所以可以简化为一行代码
			{
				//增容
				//size_t newSize = _tables.size() == 0 ? 10 : _tables.size() * 2;
				size_t newSize = GetNextPrime(_tables.size());
				vector<Node*>newTables;
				newTables.resize(newSize, nullptr);
				for (int i = 0; i < _tables.size(); i++)
				{
					Node* cur = _tables[i];
					while (cur)
					{
						Node* next = cur->_next;//记录下一个位置
						size_t index = hash(cur->_kv.first) % newTables.size();
						cur->_next = newTables[index];//cur当头
						newTables[index] = cur;//更新vector里的头
						cur = next;
					}
				}
				_tables.swap(newTables);//把新表的数据放入旧表中
			}
			size_t index = hash(kv.first) % _tables.size();//算出桶号
			//头插
			Node* newNode = new Node(kv);
			newNode->_next = _tables[index];
			_tables[index]=newNode;
			++_n;//别忘记更新有效数据的个数
			return true;
		}
		bool Erase(const K& key)
		{ 
			//if (!Find(key))//找不到这个元素 
			// 这么写也可以,但是后面删除的过程中会顺带遍历整个桶
			//{
			//	return false;
			/

本文标题为:C++深入探究哈希表如何封装出unordered_set和unordered_map