【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;
	};
}
相关推荐
波力海苔夹心脆67520 分钟前
VisionPro 与 VisionMaster 对比(上):软件定位、开发环境与核心视觉工具对照
图像处理·算法·计算机视觉·c#·视觉检测·个人开发·vp9
动词ing23 分钟前
【题目练习】盛最多水的容器
算法·目标检测
海绵宝宝转agent24 分钟前
2026-10-14算法+面经总结
java·笔记·算法·缓存
虚无的纽扣24 分钟前
【力扣刷题】第四天:三数之和、四数之和
算法·leetcode·职场和发展
ZiLing34 分钟前
2026 ROS 2 Lyrical 工程实例(一):从零搭建 AMR 激光 SLAM——Gazebo、slam_toolbox 与 Nav2 全链路跑通
算法
巴糖34 分钟前
为什么你的大模型总在胡说八道?—— top_k /top_p/temperature 调参实战手册
算法
rou39 分钟前
LeetCode410.分割数组的最大值
算法
垆边人似月.41 分钟前
华为题:字符串中最长连续数字串
开发语言·c++·算法
从小白到软工41 分钟前
C语言(中)预告
c语言·数据结构·经验分享·ai编程
_不会dp不改名_42 分钟前
leetcode_3273 数位平方和的最大值
算法·leetcode·职场和发展