【STL】unordered_set 和 unordered_map的模拟实现

一、哈希表的改造

  1. 模板参数列表的改造
  2. 增加迭代器操作
  3. 增加通过key获取value操作
cpp 复制代码
#pragma once

#include<iostream>
#include<vector>
#include<cassert>
#include<algorithm>
using namespace std;

//状态
enum State
{
	Empty,
	Delete,
	Exit
};

//哈希表中的数据
template<class T>
struct HashNode
{
	T _t;
	HashNode* next;

	HashNode(const T& t) :_t(t), next(nullptr) {}
};

template<class K, class T, class Ref,class Ptr,class KeyOfT, class Hash>
struct HashIterator
{
	typedef HashNode<T> Node;
	typedef HashIterator self;
	Node* _node;
	vector<Node*> _ht;
	HashIterator(Node* node,const vector<Node*>&ht):_node(node),_ht(ht){}

	self& operator++()
	{
		//有下一个节点
		if (_node->next)
		{
			_node = _node->next;
		}
		else
		{
			size_t hashi = Hash()(KeyOfT()(_node->_t)) % _ht.size();
			hashi++;
			while (hashi < _ht.size())
			{
				if (_ht[hashi])	break;
				hashi++;
			}
			if (hashi == _ht.size())
				_node = nullptr;
			else
				_node = _ht[hashi];
		}
		return *this;
	}
	self operator++(int)
	{
		self temp(_node);
		++_node;
		return temp;
	}
	Ptr operator->()
	{
		return &_node->_t;
	}
	Ref operator*()
	{
		return _node->_t;
	}
	bool operator!=(const HashIterator& ht)
	{
		return _node != ht._node;
	}
	bool operator==(const HashIterator& ht)
	{
		return _node == ht._node;
	}
};

template<class K, class T,class KeyOfT, class Hash>
class HashTable
{
	typedef HashNode<T> Node;
public:
	//迭代器
	typedef HashIterator<K, T, T&,T*,KeyOfT, Hash> iterator;
	typedef HashIterator<K, T, const T&,const T*,KeyOfT, Hash> const_iterator;
	iterator begin()
	{
		if(_n==0)
			return end();
		size_t i = 0;
		while ( i<_ht.size())
		{
			if(_ht[i])
				return  iterator(_ht[i], _ht);
			i++;
		}
		return end();
	}
	const_iterator begin()const
	{
		if (_n == 0)
			return end();
		size_t i = 0;
		while (i < _ht.size())
		{
			if (_ht[i])
				return  iterator(_ht[i], _ht);
			i++;
		}
		return end();
	}
	iterator end()
	{
		return iterator(nullptr, _ht);
	}
	const_iterator end()const
	{
		return iterator(nullptr, _ht);
	}

	HashTable()
	{
		_ht.resize(10);
		_n = 0;
	}
	//查找
	iterator find(const K& key)
	{
		size_t hashi = Hash()(key) % _ht.size();//定位
		Node* cur = _ht[hashi];
		while (cur)
		{
			if (KeyOfT()(cur->_t) == key)
				return iterator(cur,_ht);
			cur = cur->next;
		}
		return iterator(nullptr, _ht);
	}
	pair<iterator,bool> insert(const T& t)
	{
		iterator ret = find(KeyOfT()(t));
		if (ret._node)
			return {ret,false };

		//扩容
		if (_n == _ht.size())
		{
			vector<Node*> newht(_ht.size() * 2,nullptr);
			for (int i = 0; i < _ht.size(); i++)
			{
				Node* cur = _ht[i];
				while (cur)
				{
					Node* next = cur->next;
					size_t hashi = Hash()(KeyOfT()(_ht[i]->_t)) % newht.size();
					if (newht[i] == nullptr)
						newht[i] = cur;
					else
					{
						cur->next = newht[i];
						newht[i] = cur;
					}
					_ht[i] = next;
				}
			}
			_ht.swap(newht);
		}
		size_t hashi = Hash()(KeyOfT()(t)) % _ht.size();//定位
		Node* newnode = new Node(t);
		newnode->next = _ht[hashi];
		_ht[hashi] = newnode;
		_n++;
		return { {newnode,_ht},true };
	}

	iterator erase(const K& key)
	{
		size_t hashi = Hash()(key) % _ht.size();//定位
		Node* prev = nullptr;
		Node* cur = _ht[hashi];
		Node* ret = nullptr;
		while (cur)
		{
			if (KeyOfT()(cur->_t) == key)
			{
				Node* temp = cur;
				ret = ++temp;

				if (prev == nullptr)
				{					
					_ht[hashi] = nullptr;
				}
				else
				{
					prev->next = cur->next;
				}
				delete cur;
				cur = nullptr;
				_n--;
				return{ ret, _ht };
			}
			prev = cur;
			cur = cur->next;
		}
		return { nullptr,_ht };
	}
private:
	vector<Node*> _ht;
	size_t _n;
};

二、unordered_set 的模拟实现

cpp 复制代码
#pragma once

#include"HashBucket.h"
//对于int 、double、size_t 、int* 等类型
template<class K>
struct HashFunc_set
{
	size_t operator()(const K& key)
	{
		return size_t(key);
	}
};

//对于string 的特化处理
template<>
struct HashFunc_set<string>
{
	size_t operator()(const string& key)
	{
		size_t ret = 0;
		for (const auto& e : key)
			ret = ret * 31 + e;
		return ret;
	}
};

template<class K,class Hash = HashFunc_set<K>>
class unordered_set
{
	typedef K T;//和map相称
	struct KeyOfT
	{
		const K& operator()(const T& t)
		{
			return t;
		}
	};
	typedef typename HashTable<K, T, KeyOfT, Hash>::iterator iterator;
	typedef typename HashTable<K, T, KeyOfT, Hash>::const_iterator const_iterator;
public:
	iterator begin()
	{
		return _ht.begin();
	}
	iterator end()
	{
		return _ht.end();
	}
	const_iterator begin()const
	{
		return _ht.begin();
	}
	const_iterator end()const
	{
		return _ht.end();
	}
	iterator find(const K& key)
	{
		return _ht.find(key);
	}
	pair<iterator, bool> insert(const T& t)
	{
		return _ht.insert(t);
	}
	iterator erase(const K& key)
	{
		return _ht.erase(key);
	}
private:
	HashTable<K, T, KeyOfT, Hash> _ht;
};

三、unordered_map 的模拟实现

cpp 复制代码
#pragma once

#include"HashBucket.h"
//对于int 、double、size_t 、int* 等类型
template<class K>
struct HashFunc_map
{
	size_t operator()(const K& key)
	{
		return size_t(key);
	}
};

//对于string 的特化处理
template<>
struct HashFunc_map<string>
{
	size_t operator()(const string& key)
	{
		size_t ret = 0;
		for (const auto& e : key)
			ret = ret * 31 + e;
		return ret;
	}
};

template<class K,class V,class Hash= HashFunc_map<K>>
class unordered_map
{
	typedef pair<K, V> T;//和map相称
	struct KeyOfT
	{
		const K& operator()(const T& t)
		{
			return t.first;
		}
	};
	typedef typename HashTable<K, T,KeyOfT, Hash>::iterator iterator;
	typedef typename HashTable<K, T,KeyOfT, Hash>::const_iterator const_iterator;
public:
	iterator begin()
	{
		return _ht.begin();
	}
	iterator end()
	{
		return _ht.end();
	}
	const_iterator begin()const
	{
		return _ht.begin();
	}
	const_iterator end()const
	{
		return _ht.end();
	}
	iterator find(const K& key)
	{
		return _ht.find(key);
	}
	pair<iterator, bool> insert(const T& t)
	{
		return _ht.insert(t);
	}
	iterator erase(const K& key)
	{
		return _ht.erase(key);
	}
	V& operator[](const K& key)
	{
		pair<iterator, bool> ret = insert({ key,V() });
		return ret.first->second;
	}
private:
	HashTable<K, T,KeyOfT,Hash> _ht;
};
相关推荐
亦枫Leonlew2 分钟前
微积分复习笔记 Calculus Volume 2 - 5.1 Sequences
笔记·数学·微积分
飞飞-躺着更舒服5 分钟前
【QT】实现电子飞行显示器(改进版)
开发语言·qt
武昌库里写JAVA21 分钟前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
爱码小白35 分钟前
网络编程(王铭东老师)笔记
服务器·网络·笔记
CYBEREXP200838 分钟前
MacOS M3源代码编译Qt6.8.1
c++·qt·macos
ZSYP-S1 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
yuanbenshidiaos1 小时前
c++------------------函数
开发语言·c++
yuanbenshidiaos1 小时前
C++----------函数的调用机制
java·c++·算法
唐叔在学习1 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
程序员_三木1 小时前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js