C++进阶-哈希封装(unordered_set和unordered_set)

1. 哈希封装思路

首先,内层用的是哈希表,哈希表使用泛型编程,外层unordered_map和unordered_set给与相应的参数,之后编译器自动生成。

2. 哈希封装的模拟实现

主要由三个头文件进行封装,My_unordered_map.h,My_unordered_set.h和HashTable.h头文件,分别装有My_unordered_map,My_unordered_set,哈希表。

2.1 HashTable.h

除留取余法的仿函数,让数据类型转换为可以取余的类型

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

// 特化
template<>
struct HashFunc<string>
{
   
	// abcd
	// bcad
	// aadd
	// BKDR
	size_t operator()(const string& key)
	{
   
		size_t hash = 0;
		for (auto ch : key)
		{
   
			hash *= 131;
			hash += ch;
		}

		return hash;
	}
};

2.1.1 节点数据类

用来初始化节点,定义节点数据

// 节点数据
template<class T>
struct HashNode
{
   
	T _data;// 节点数据
	HashNode<T>* _next;// 下一个节点地址

	// 构造函数
	HashNode(const T& data)
		:_data(data),
		_next(nullptr)
	{
   }
};

2.1.2 迭代器类

operator++()

  1. 节点是这个表索引位置下的最后一个节点
    a.找下一个不为空的数组索引的指针,找到
    b.没找到,直接置空
    在这里插入图片描述

  2. 节点不是表索引的位置下的最后一个节点,直接找下一个节点

// ++
	// 如果当前节点是这个表的_tables[i]的最后一个节点,++需要找到数组的下一个索引
	// 所以需要引入表,才可以找到下一个位置
	// 1.节点是这个表索引位置下的最后一个节点
	//​	a.找下一个不为空的数组索引的指针,找到
	//	​b.没找到,直接置空
	// 2.节点不是表索引的位置下的最后一个节点,直接找下一个节点
	Self& operator++()
	{
   
		// 2.节点不是表索引的位置下的最后一个节点,直接找下一个节点
		if (_node->_next)
		{
   
			_node = _node->_next;
		}
		else// 1.节点是这个表索引位置下的最后一个节点
		{
   
			Hash hs;
			KeyOfT kot;
			// 首先找到这个表上当前节点的索引位置
			size_t i = hs(kot(_node->_data)) % _pht->_tables.size();

			++i;
			// 寻找这个表上下一个指向不为空的索引下的指针
			for (; i < _pht->_tables.size(); i++)
			{
   
				// 如果不为空,则就找到了
				if (_pht->_tables[i])
				{
   
					break;
				}
			}

			// 如果遍历完表也没找到指向不为空的索引指针
			if (i == _pht->_tables.size())
			{
   
				_node = nullptr;
			}
			else
			{
   
				_node = _pht->_tables[i];// _node指向这个索引位置下指针指向的第一个节点
			}

		}

		return *this;
	}

由于如果当前节点是当前索引的最后一个节点时,则要找下一个指向不为空的索引指针,所以要获取当前表。所以成员会引入
const HashTable<K, T, KeyOfT, Hash> _pht;// 引用一个表的指针*
但是哈希表中也会引入迭代器,所以两两形式互相依赖,所以需要在迭代器类的前面进行哈希表类的声明


// 由于__HTIterator类和HashTable互相依赖,__HTIterator中引入表的成员变量,HashTable也引入了迭代器
// 两两互相依赖
// 由于__HTIterator先定义的,得HashTable类在前面声明,否则无法找到HashTable
template<class K, class T, class KeyOfT, class Hash>
class HashTable;

迭代器类的总体代码

// 哈希桶的迭代器
//        data														T&          T*
template<class K,class T,  class KeyOfT, class Hash, class Ref, class Ptr>
struct __HTIterator
{
   
public:
	// 重定义节点数据
	typedef HashNode<T> Node;

	// 重定义迭代器数据
	typedef __HTIterator<K, T, KeyOfT, Hash, Ref,Ptr> Self;

	// 构造函数
	__HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht)
		:_node(node),
		_pht(pht)
	{
   }

	// 解引用
	// T&
	Ref operator*()
	{
   
		return _node->_data;
	}

	// 解引用
	// T*
	Ptr operator->(</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值