哈希表开散列哈希桶实现,unordered_map和unordered_set的模拟实现

template<class K>
struct keyOfValue
{
	const K& operator()(const K& key)
	{
		return key;
	}
};

//开散列: 指针数组 + 单链表
template<class V>
struct HashNode
{
	V _value;
	HashNode<V>* _next;

	HashNode(const V& _val = V())
		:_value(val)
		,_next(nullptr)
	{}
};

//前置声明
template<class K, class V, class KeyOfValue, class HF>
class HashTable;

template<class K, class V, class KeyOfValue, class HF>
struct HashIterator
{
	typedef HashNode<V> Node;
	typedef HashIterator<K, V, KeyOfValue, HF> Self;
	typedef HashTable<K, V, KeyOfValue, HF> HT;

	Node* _node;
	HT* _ht;

	HashIterator(Node* node, HT* ht)
		:_node(node)
		,_ht(ht)
	{}

	V& operator*()
	{
		return _node->_value;
	}

	V* operator&()
	{
		return &_node->_value;
	}

	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	Self& operator++()
	{
		if (_node->_next)
		{
			_node = _node->_next;
		}
		else
		{
			//找到下一个非空链表的头结点
			// 1. 定位当前节点在哈希表中的位置
			//kov: 获取value的key
			KeyOfValue kov;
			//hf: 获取key转换之后的整数
			HF hf;
			size_t idx = hf(kov(_node->_value) % _ht->_table.size();
			// 2. 从表中的下一个位置开始查找第一个非空链表的头结点
			++idx;
			Node* cur = _ht->_table[idx];
			for (; idx < _ht->table.size(); idx++)
			{
				if (_ht->table[idx])
				{
					_node = _ht->table[idx];
					break;
				}
			}
			// 3. 判断是否找到一个非空的头结点
			if (idx == _ht->table.size())
				_node = nullptr;
		}
		return *this;
	}
};

template<class K, class V, class KeyOfValue, class HF>
class HashTable
{
public:
	//迭代器声明为友元类
	template <class K, class V, class KeyOfValue, class HF>
	friend struct HashIterator;
	typedef HashNode<V> Node;
	typedef HashIterator<K, V, KeyOfValue, HF> iterator;

	iterator begin()
	{
		//第一个非空链表的头结点
		for (size_t i = 0; i < _table.size(); i++)
		{
			Node* cur = _table[i];
			if (cur)
				return iterator(cur, this);
		}
		return iterator(nullptr.this);
	}

	iterator end()
	{
		return iterator(nullptr, this);
	}

	pair<iterator, bool> insert(const V& value)
	{
		checkCapacity();
		//1. 计算位置
		KeyOfValue kov;
		HF hf;
		int idx = hf(kov(value)) % _table.size();
		//2. 搜索key是否已经存在
		Node* cur = _table[idx];
		while (cur)
		{
			if (kov(cur->_value) == kov(value))
			return make_pair(iterator(cur, this), false);
			cur = cur->_next;
		}
		//3. 插入: 头插
		cur = new Node(value);
		cur->_next = _table[idx];
		_table[idx] = cur;
		++_size;
		return make_pair(iterator(cur, this), true);
	}

	void checkCapacity()
	{
		if (_size == _table.size())
		{
			size_t newSize = _size == 0 ? 5 : 2 * _size;
			vector<Node*> newHt;
			newHt.resize(newSize);
			KeyOfValue kov;
			HF hf;
			//遍历旧表中的非空单链表
			for (size_t i = 0; i < _table.size(); i++)
			{
				Node* cur = _table[i];
				//遍历当前链表
				while (cur)
				{
					//0.记录旧表中的下一个元素
					Node* next = cur->_next;
					//1.计算新的位置
					int idx = hf(kov(cur->_value)) % newHt.size();
					//2.头插
					cur->_next = newHt[idx];
					newHt[idx] = cur;
					//3.处理下一个元素
					cur = next;
				}
				_table[i] = nullptr;
			}
			_table.swap(newHt);
		}
	}

	Node* find(const K& key)
	{
		if (_table.size() == 0)
			return nullptr;
		HF hf;
		int idx = hf(key) % _table.size();
		Node* cur = _table[idx];
		KeyOfValue kov;
		while (cur)
		{
			if (kov(cur->_value) == key)
				return cur;
			cur = cur->_next;
		}
		return nullptr;
	}

	bool erase(const K& key)
	{
		HF hf;
		int idx = hf(key) % _table.size();
		Node* cur = _table[idx];
		//单链表删除逻辑
		Node* prev = nullptr;
		KeyOfValue kov;
		while (cur)
		{
			if (kov(cur->_value) == key)
			{
				//删除
				//判断删除的是否为头结点
				if (prev == nullptr)
				{
					_table[idx] = cur->_next;
				}
				else
				{
					prev->_next = cur->_next;
				}
				delete cur;
				_size--;
				return true;
			}
			else
			{
				prev = cur;
				cur = cur->_next;
			}
		}
		return false;
	}

private:
	vector<Node*>_table;
	size_t _size = 0;
};

//字符转换为整数
struct StrToInt
{
	size_t operator()(const string& str)
	{
		size_t hash = 0;
		for (const auto& ch : str)
		{
			hash = hash * 131 + ch;
		}
		return hash;
	}
};

template<class K>
struct hashFun
{
	size_t operator()(const K& key)
	{
		return key;
	}
};

template<class K, class V, class HF = hashFun<K>>
class UnorderedMap
{
	struct MapKeyOfValue
	{
		const K& operator()(const pair<K, V>& value)
		{
			return value.first;
		}
	};
public:
	typedef typename HashTable<K, pair<K, V>, MapKeyOfValue, HF>::iterator iterator;
	pair<iterator, bool> insert(const pair<K, V>& value)
	{
		return _ht.insert(value);
	}
	V& operator[](const K& key)
	 {
 	 pair<iterator, bool> ret = _ht.insert(make_pair(key, V()));
	  return ret.first->second;
	 }
private:
	HashTable<K, pair<K, V>, MapKeyOfValue, HF> _ht;
};

template<class K, class HF = hashFun<K>>
class UnorderedSet
{
	struct SetKeyOfValue
	{
		const K& operator()(const K& value)
		{
			return value;
		}
	};
public:
	typedef typename HashTable<K, K, keyOfValue, HF>::iterator iterator;
	iterator begin()
	{
		return _ht.begin();
	}

	iterator end()
	{
		return _ht.end();
	}

	pair<iterator, bool> insert(const K& value)
	{
		return _ht.insert(value);
	}
private:
	HashTable<K, K, SetKeyOfValue, HF> _ht;
};
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值