哈希表的实现(1)----除留余数法实现

news2024/9/28 7:22:54

一,哈希表的介绍

 哈希表是一种通过哈希思想实现的一种数据结构。哈希表这种数据结构的特点便是可以通过一个值快速的定位这个值所在的位置实现插入,删除,查找。在这篇博客里面,我们便来实现一个通过除留余数法实现的一个哈希表。

二,哈希表的实现

1,哈希表的结构

因为这里要实现的是一个除留余数法实现的一个哈希表,所以是要用到线性探测的方法的。所以在哈希表内部的成员里便要一个连续的存储结构,所以便可以用一个vector<>

vector里面的元素该用什么类型呢?因为要实现一个比较漂亮的哈希表,所以这个哈希表里面的元素最好能够表示当前的状态,所以这里我们得自己定义hashData。还有为了方便的统计哈希表里面的元素个数,我们又得定义一个_n表示哈希表里面的元素个数。

结构定义如下:

	enum State
	{
		EMPTY,//代表空状态
		EXIST,//代表存在状态
		DELETE//代表删除状态
	};

    template<class K,class V>
	struct hashData
	{
		State _st;//状态
		pair<K, V>_kv;//元素数据
	};

	template<class K,class V>
	class HashTable
	{

	private:
		vector<hashData<K, V>> _hashtables;
		size_t _n = 0;//表示元素个数,并且要初始化,并且一定得是size_t类型的变量(预防插入一个关键值为负数的元素)
	};

二,插入操作实现

插入操作的实现的实现主要分为以下几步:

1,计算插入值对应的位置。

2,如果这个位置上面已经有元素了便要往后线性探测。(这里便是出现了哈希冲突)

3,如果插入的元素已经把表给填满了便要开新表,然后将旧表中的值重新映射填入到新表中。然后再交换给旧表。

插入操作优化的点:

在插入时最讨厌的便是出现哈希冲突,所以为了减少哈希冲突的出现便可以在定义一个叫做负载因子。一般负载因子的值达到了0.7便要开始扩容。

代码实现如下:

bool Insert(const pair<K, V>key)
		{
			if (_n * 10 / _hashtables.size() == 7)
			{
				int newsize = 2 * _hashtables.size();
				HashTable<K,V>newHash;
				for (int i = 0;i < _hashtables.size();i++)
				{
					if (_hashtables[i]._st == EXIST)
					{
						newHash.Insert(_hashtables[i]._kv);
					}
				}

				_hashtables.swap(newHash._hashtables);
			}


			int hashi = key.first % _hashtables.size();
			while (_hashtables[hashi]._st == EXIST)
			{
				hashi++;
				hashi %= _hashtables.size();
			}
			_hashtables[hashi]._kv = key;
			_hashtables[hashi]._st = EXIST;
			_n++;
			return true;
		}

三,查找操作

哈希表的查找操作步骤如下:

1,通过除留余数法计算出hashi。

2,通过hashi定位到指定位置,如果这个指定位置的状态是EMPTY便停止。反之便继续找。

3,找到了便将该位置返回。

4,找不到便返回一个nullptr。

实现代码如下:

hashData<K, V>* Find(const pair<K, V>key)
		{
			size_t hashi = key .first% _hashtables.size();
			while (_hashtables[hashi]._st != EMPTY)
			{
				if (_hashtables[hashi]._st == EXIST&&_hashtables[hashi]._kv == key)
				{
					return &_hashtables[hashi];
				}

				hashi++;
				hashi %= _hashtables.size();
			}

			return nullptr;
		}

在实现了查找操作以后便可以在插入操作里面实现一个不能插入相同元素的功能。代码如下:

if (Find(key))
{
	return false;
}

四,删除操作

这里的删除操作实现的是一种伪删除法。删除时通过Find()找到对应的值,然后将这个值对应的状态改为DELETE即可。

代码:

bool Erase(const pair<K, V>key)
{
	hashData<K, V>* ret = Find(key);
	if (ret)
	{
		ret->_st = DELETE;
		return true;
	}
    return false;
}

五,全部代码

#include<iostream>
#include<vector>
using namespace std;

namespace Hash
{
	enum State
	{
		EMPTY,//代表空状态
		EXIST,//代表存在状态
		DELETE//代表删除状态
	};

    template<class K,class V>
	struct hashData
	{
		State _st;//状态
		pair<K, V>_kv;//元素数据
	};

	template<class K,class V>
	class HashTable
	{
	public:
		HashTable()
		{
			_hashtables.resize(10);
		}

		bool Insert(const pair<K, V>key)
		{
			if (Find(key))
			{
				return false;
			}

			if (_n * 10 / _hashtables.size() == 7)
			{
				int newsize = 2 * _hashtables.size();
				HashTable<K,V>newHash;
				for (int i = 0;i < _hashtables.size();i++)
				{
					if (_hashtables[i]._st == EXIST)
					{
						newHash.Insert(_hashtables[i]._kv);
					}
				}

				_hashtables.swap(newHash._hashtables);
			}


			int hashi = key.first % _hashtables.size();
			while (_hashtables[hashi]._st == EXIST)
			{
				hashi++;
				hashi %= _hashtables.size();
			}
			_hashtables[hashi]._kv = key;
			_hashtables[hashi]._st = EXIST;
			_n++;
			return true;
		}

		hashData<K, V>* Find(const pair<K, V>key)
		{
			size_t hashi = key .first% _hashtables.size();
			while (_hashtables[hashi]._st != EMPTY)
			{
				if (_hashtables[hashi]._st == EXIST&&_hashtables[hashi]._kv == key)
				{
					return &_hashtables[hashi];
				}

				hashi++;
				hashi %= _hashtables.size();
			}

			return nullptr;
		}

		bool Erase(const pair<K, V>key)
		{
			hashData<K, V>* ret = Find(key);
			if (ret)
			{
				ret->_st = DELETE;
				return true;
			}
			return false;
		}

		void Print()
		{
			for (int i = 0;i < _hashtables.size();i++)
			{
				if (_hashtables[i]._st == EXIST)
				{
					printf("->%d\n",_hashtables[i]._kv.second);
				}
				else if (_hashtables[i]._st == DELETE)
				{
					printf("%d->D\n", _hashtables[i]._kv.second);
				}
				else
				{
					printf("-> \n");
				}
			}
		}

	private:
		vector<hashData<K, V>> _hashtables;
		size_t _n = 0;//表示元素个数,并且要初始化
	};

	void HT1()
	{
		HashTable<int, int>hash;
		hash.Insert(make_pair<int, int>(1, 1));
		hash.Insert(make_pair<int, int>(1, 8));
		hash.Insert(make_pair<int, int>(1, 9));
		hash.Insert(make_pair<int, int>(1, 12));
		hash.Insert(make_pair<int, int>(1, 12));
		hash.Insert(make_pair<int, int>(1, 19));
		hash.Insert(make_pair<int, int>(1, 10));
		hash.Insert(make_pair<int, int>(1, 20));

		hash.Erase(make_pair<int, int>(1, 10));
		hash.Insert(make_pair<int, int>(1, 30));
		hash.Print();

	}



}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1379570.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tl431几种不常见的接法

tl431可调电源电路图分析 精密电压基准IC TL431是我们常见的精密电压基准IC &#xff0c;应用非常广泛。其输出压连续可调达36V&#xff0c;工作电流范围宽达0.1--100mA&#xff0c;动态电阻典型值为0.22欧&#xff0c;输出杂波低。图1是利用它作电压基准和驱动外加场效应管K7…

泛微OA-Ecology8表单中填充用友U8数据

文章目录 1、需求及效果1.1 需求1.2 效果 2、思路及实现步骤2.1 思路2.2 实现步骤 3.结语 1、需求及效果 1.1 需求 在OA中填写表单中时候&#xff0c;比如物料号还需要从U8中查找后才能填写&#xff0c;非常的麻烦。想要在填写表单的时候可以搜索&#xff0c;并且带出其他的关…

如何使用SVN查看旧版本

和目录 第一步&#xff1a;打开SVN客户端 第二步&#xff1a;浏览历史版本 第三步&#xff1a;还原历史版本 结论 Subversion (缩写为SVN)是一种常用的版本控制系统&#xff0c;它可以帮助团队协作开发软件项目。除了基本的版本控制功能外&#xff0c;SVN还提供了许多其他功…

HackTheBox - Medium - Linux - Faculty

Faculty Faculty 是一台中型 Linux 机器&#xff0c;具有 PHP Web 应用程序&#xff0c;该应用程序使用的库容易受到本地文件包含的影响。利用该库中的 LFi 会泄露一个密码&#xff0c;该密码可用于通过 SSH 以名为“gbyolo”的低级用户身份登录。用户“gbyolo”有权作为“dev…

【kafka】记录用-----------1

主题&#xff08;topic&#xff09;&#xff1a;消息的第一次分类 根据人为的划分条件将消息分成不同的主题 主题的划分是人为的根据不同的任务情景去划分 比如&#xff0c;我们有两个主题&#xff0c;一个是"订单"&#xff0c;另一个是"库存"。每个主题代…

记录一个Insert姿势引起的MySQL从库上查不到数据的问题

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 问题描述&#xff1a; 某测试环境的MySQL用了两台节点&#xff0c;主从同步结构。忽然有研发同学反映说MySQL的主从不同步了。他…

亚马逊测评怎么做?

亚马逊作为全球最大的跨境电商公司&#xff0c;吸引了很多的中国卖家入驻&#xff0c;行业的内卷也是越来越严重&#xff0c;很多做过国内电商的都知道测评可以提高产品权重&#xff0c;快速提升产品销量 而测评模式主要有两种&#xff1a; 真人测评 优点&#xff1a;老外手…

【嵌入式——QT】QT静态编译

【嵌入式——QT】QT静态编译 QT下载查看文档下载Visual Studio打开命令行模式编译添加QT到Qt Creator编译示例 QT下载 下载地址 进入目录&#xff0c;我这里选择的qt-everywhere-src-5.14.1.zip。 查看文档 解压压缩包打开源码&#xff0c;查看README文件&#xff0c;里面…

解决文字识别中误识别问题的秘籍

随着人工智能技术的不断发展&#xff0c;文字识别技术已经广泛应用于各个领域&#xff0c;如智能客服、智能家居、自动驾驶等。然而&#xff0c;在实际应用中&#xff0c;文字识别技术也面临着误识别的问题。误识别不仅会影响用户体验&#xff0c;还可能导致严重的后果。因此&a…

UE5 实现RPG游戏操作控制

在UE5以后&#xff0c;epic抛弃了之前的那一套操作输入系统&#xff0c;使用了一套新的增强输入作为替代&#xff0c;目的主要是解决经常切换操作时的问题&#xff08;操作人物上车以后&#xff0c;可以直接切换成操作汽车的一套输入&#xff09;接下来&#xff0c;将实现如何使…

双目测距工程Stereo-Vision-master学习笔记

硬件&#xff1a; 首先要要把两个摄像头固定到支架上&#xff0c;并且两个摄像头的间距应该在110mm&#xff0c;两个摄像头没有落差 相机的内参数包括焦距、主点坐标、像素尺寸等&#xff0c;这些参数决定了相机成像的几何变换关系。内参数是相机固有的属性&#xff0c;不会随…

RK3568驱动指南|第十二篇 GPIO子系统-第128章 GPIO入门实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

【期末考试】网络综合复习宝典

相关链接 网络复习思维导图&#xff08;HCIP&#xff09;https://www.edrawsoft.cn/viewer/public/s/038e2370897928 详述循环冗余校验CRC码https://blog.csdn.net/liht_1634/article/details/124328005?app_version6.2.6&codeapp_1562916241&csdn_share_tail%7B%22…

用通俗易懂的方式讲解:十分钟读懂 Stable Diffusion 运行原理

AIGC 热潮正猛烈地席卷开来&#xff0c;可以说 Stable Diffusion 开源发布把 AI 图像生成提高了全新高度&#xff0c;特别是 ControlNet 和 T2I-Adapter 控制模块的提出进一步提高生成可控性&#xff0c;也在逐渐改变一部分行业的生产模式。惊艳其出色表现&#xff0c;也不禁好…

windows server 2012、2019服务器定时重启

手动设置定时任务 1.开始菜单&#xff0c;找到“计划任务程序”; 如果无法创建基本任务的话&#xff0c;可能是系统中的“Task Scheduler”服务没有启动&#xff0c;你可在运行中键入“ services.msc”&#xff0c;查看“Task Scheduler”服务是否被设置成了“已禁用”&#x…

2024 年 8 款最好的PDF阅读和编辑软件

写出好的内容本身就是一门艺术。写作中的错误会让你看起来粗心大意或无能为力——这两种情况都不利于你的职业形象。没有任何软件能够取代现实生活中可以指出您写作错误的编辑器。幸运的是&#xff0c;有些软件已经接近并仍在改进它们的服务以帮助您清理工作。 编辑PDF很昂贵&…

k8s集群配置NodeLocal DNSCache

一、简介 当集群规模较大时&#xff0c;运行的服务非常多&#xff0c;服务之间的频繁进行大量域名解析&#xff0c;CoreDNS将会承受更大的压力&#xff0c;可能会导致如下影响&#xff1a; 延迟增加&#xff1a;有限的coredns服务在解析大量的域名时&#xff0c;会导致解析结果…

【Maven】002-Maven 安装和配置

【Maven】002-Maven 安装和配置 文章目录 【Maven】002-Maven 安装和配置一、官网1、官网2、历史版本列表 二、下载 Maven 3.8.8 版本1、进入 Maven 3.8.8 版本发行说明页2、进入下载页3、下载4、下载得到 apache-maven-3.8.8-bin.zip 三、Maven 安装1、将安装包解压到想放置的…

牛客周赛 Round 1 解题报告 | 珂学家 | 分类计数 + 同余DP

前言 生于生时&#xff0c;亡于亡刻。遵从自心&#xff0c;尽人之事。 整体评价 终于等来了侧重面试的比赛&#xff0c;而且题量刚刚好&#xff0c;不超纲&#xff0c;不涉及算法竞赛。 第一场的比赛&#xff0c;感觉题目出的比较典&#xff0c;A是简单模拟&#xff0c;B则是…

NX二次开发PK获取对象类型

PK_ENTITY_ask_class(),获取对象类型建议用这个函数&#xff0c;比较通用&#xff0c;包含所有对象类型&#xff0c;可以替代UF_MODL_ask_edge_type(),UF_MODL_ask_body_type(),UF_MODL_ask_face_type()等函数 PK_ENTITY_t entity; PK_CLASS_t PK_TYPE; PK_ENTITY_ask_class(e…