【C++】哈希桶

在解决哈希冲突问题时,可以使用闭散列和开散列的方式。开散列法又叫做链地址法,首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头节点存储在哈希表中。

开散列中每一个桶中放的都是发生哈希冲突的元素,这里的哈希桶存储一定数据之后,需要扩容,如果不扩容,不断插入后哈希桶会越来越长,效率得不到保障(负载因子控制在1,平均一个哈希桶一个数据)。

cpp 复制代码
#pragma once
#include <iostream>
#include <vector>
#include<cstdio>

using namespace std;

namespace hash_bucket
{
	template<class K, class V>
	struct HashNode
	{
		pair<K, V> _kv;
		HashNode<K, V>* _next;

		HashNode(const pair<K, V>& kv)
			:_kv(kv)
			,_next(nullptr)
		{}
	};

	template<class K, class V>
	class HashTable
	{
	public:
		typedef HashNode<K, V> Node;

		HashTable()
		{
			_table.resize(10, nullptr);
		}

		bool Insert(const pair<K, V>& kv)
		{
			if (Find(kv.first))
			{
				return false;
			}
			// 负载因子到1就扩容
			if (_n == _table.size())
			{
				size_t newSize = _table.size() * 2;
				vector<Node*> newTable;
				newTable.resize(newSize, nullptr);
				for (size_t i = 0; i < _table.size(); ++i)
				{
					Node* cur = _table[i];
					while (cur)
					{
						Node* next = cur->_next;
						size_t hashi = cur->_kv.first % newSize;
						cur->_next = newTable[hashi];
						newTable[hashi] = cur;

						cur = next;
					}

					_table[i] = nullptr;
				}
				_table.swap(newTable);
			}

			size_t hashi = kv.first % _table.size();
			// 头插
			Node* newnode = new Node(kv);
			newnode->_next = _table[hashi];
			_table[hashi] = newnode;
			++_n;
			return true;
		}

		void Print()
		{
			for (int i = 0; i < _table.size(); ++i)
			{
				printf("[%d]->", i);
				Node* cur = _table[i];
				while (cur)
				{
					cout << cur->_kv.first << "->";
					cur = cur->_next;
				}
				printf("NULL\n");
			}
		}

		Node* Find(const K& key)
		{
			size_t hashi = key % _table.size();
			Node* cur = _table[hashi];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					return cur;
				}
				cur = cur->_next;
			}
			return nullptr;
		}

		bool Erase(const K& key)
		{
			size_t hashi = key % _table.size();
			Node* prev = nullptr;
			Node* cur = _table[hashi];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					// delete
					if (prev == nullptr)
					{
						_table[hashi] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;
					}
					delete cur;
					return true;
				}
				prev = cur;
				cur = cur->_next;
			}
			return false;

		}

		~HashTable()
		{
			for (size_t i = 0; i < _table.size(); ++i)
			{
				Node* cur = _table[i];
				while (cur)
				{
					Node* next = cur->_next;
					delete cur;
					cur = next;
				}
				_table[i] = nullptr;
			}
		}
	private:
		vector<Node*> _table;
		size_t _n = 0;
	};
}
相关推荐
西安邮电大学4 分钟前
贪心算法详细讲解
java·后端·其他·算法·面试
开源Z4 分钟前
LeetCode 135 · 分发糖果:两次扫描,先左后右取最大
算法·leetcode
装不满的克莱因瓶43 分钟前
掌握生成对抗网络(GAN)的优化目标与评估指标——从博弈函数到生成质量衡量体系
人工智能·python·深度学习·算法·机器学习
技术小黑1 小时前
CNN算法实战系列06 | InceptionV1实现猴痘病识别
深度学习·算法·cnn·inceptionv1
qq_297574671 小时前
设计模式系列文章(基础篇第22篇):访问者模式——分离数据结构与操作,实现灵活扩展
数据结构·设计模式·访问者模式
云淡风轻~窗明几净1 小时前
角谷猜想的任意算法测试
数据结构·人工智能·算法
代码中介商1 小时前
关键路径解析:项目管理的工期奥秘
数据结构
happygrilclh1 小时前
赚外快了:等离子表面处理机电源算法需求说明
算法
ji198594431 小时前
MATLAB 求散点曲线斜率
开发语言·算法·matlab
kaikaile19952 小时前
MATLAB 实现:Koch & Zhao 图像水印算法(DCT域)
开发语言·算法·matlab