C++中unordered_map/set模拟实现

C++中Hash表

​ 在C++中实现的Hash表为unordered_map和unordered_set这两个容器,其底层实现都是使用hash表实现的(关于hash表的详细细节和实现,这篇blog有讲解:Hash表(C++)_c++ hash表-blog),本篇将用该博客中提到的hash桶的方式实现unordered_map和unordered_set这两个容器,也就是使用模板将博客中的hash桶包装成这两个容器。

​ unordered_map中存放的是键值对,根据键值在hash桶中存放键值及其对应的值(key-value)。

​ unordered_set中只存放了键值(key)。

hash桶

​ 在Hash表(C++)_c++ hash表-blog该博客中并没有实现hash桶的迭代器,为了实现unordered_map和unordered_set,还需要在hash桶的底层实现其迭代器,给unordered_map和unordered_set的迭代去造轮子。

​ 全部代码如下(文件名:HashTable.h):

#pragma once
#include <vector>
#include <string>
#include <iostream>
using namespace std;

// hash函数的特化
template <class K>
struct HashFunc {
   
   
	size_t operator()(const K& key) {
   
   
		return (size_t)key;
	}
};

template<>
struct HashFunc <string> {
   
   
	size_t operator()(const string& key) {
   
   
		size_t hash = 0;
		for (auto e : key)
			hash = hash * 131 + e;
		return hash;
	}
};

namespace Hash_Bucket {
   
   
	// 节点
	template<class K, class T>
	struct HashNode {
   
   
		T _data;
		HashNode* _next = nullptr;

		HashNode() = default;
		HashNode(const T& data)
			: _data(data)
			, _next(nullptr)
		{
   
   }
	};

	// 前置声明hash桶
	template <class K, class T, class KeyOfT, class Hash>
	class HashTable;
	/// <summary>
	/// <typeparam name="K"></typeparam>		key
	/// <typeparam name="T"></typeparam>		value
	/// <typeparam name="Ref"></typeparam>		传入引用,因为是map和set的底层,他们会分别传入引用,所以需要单独设计出来
	/// <typeparam name="Ptr"></typeparam>		传入指针,和引用同样的道理
	/// <typeparam name="KeyOfT"></typeparam>	仿函数,operator()的返回值是map和key对应的key
	/// <typeparam name="Hash"></typeparam>		hash函数,也是由map和set分别传入
	/// </summary>
	template <class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>
	class __HTiterator {
   
   
		typedef HashNode<K, T> Node;
		typedef __HTiterator<K, T, Ref, Ptr, KeyOfT, Hash> Self;
		typedef HashTable<K, T, KeyOfT, Hash> hashtable;
	public:
		__HTiterator()
			: _node(nullptr)
			, _pht(nullptr)
		{
   
   }

		__HTiterator(Node* node, const hashtable* pht) {
   
   
			_node = node;
			_pht = pht;
		}

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

		Ref operator*() {
   
   
			return _node->_data;
		}

		Ptr operator->() {
   
   
			return &(_node->_data);
		}
		

		/// <summary>
		/// hash表的迭代器是单向迭代器,所以只能++,前置++和后置++逻辑一样
		/// 本篇就只实现后置++
		/// </summary>
		Self& operator++() {
   
   
			// 若当前元素的下一个位置还存在元素,那么直接传递下一个元素
			if (_node->_next) {
   
   
				_node = _node->_next;
				return *this;
			}
			Hash hf;
			KeyOfT kot;
			// 计算hash位置
			size_t index = hf(kot(_node->_data)) % _pht->_tables.size();
			++index;
			for (size_t i = index; i < _pht->_tables.size(); i++) {
   
   
				Node* cur = _pht->_tables[i];
				if (cur != nullptr) {
   
   
					_node = cur;
					return *this;
				}
			}
			// 走到这里就说明没有找到对应的元素,已经是最后一个
			// 所以将迭代器指向nullptr
			_node = nullptr;
			return *this;
		}

	private:
		// 存放结点指针和hash桶的指针
		Node* _node;
		const hashtable* _pht;
	};

	template <class K, class T, class KeyOfT, class Hash>
	class HashTable {
   
   
		typedef HashNode<K, T> Node;
		// 将迭代器设置为友员
		template <class K, class T, class Ref, class Ptr, class KeyOfT, class Hash >
		friend class __HTiterator;

	public:
		typedef __HTiterator<K, T,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值