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

一,哈希表的介绍

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

二,哈希表的实现

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();

	}



}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Alibaba-> EasyExcel 整理3

1 导入依赖 <!-- easyExcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version >3.2.1</version><exclusions><exclusion><artifactId>poi-ooxml-schemas</art…

基于SpringBoot+Vue实现的二手交易系统

系统介绍 校园二手交易网站是一种专门针对有二手物品交易需求用户的二手交易的网站。它的设计和开发主要是为了满足用户之间的二手物品交易需求&#xff0c;方便大家在线买卖二手物品。近年来&#xff0c;随着互联网技术的发展&#xff0c;人们越来越喜欢在线购物&#xff0c;…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-6 线性控制器设计Linear Controller Design

本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-6 线性控制器设计Linear Controller Design

31 树的存储结构一

无法直接用数组表示树的逻辑结构&#xff0c;但是可以设计结构体数组对节点间的关系进行描述&#xff1a;【如表】 这样做的问题&#xff1a; 可以利用 组织链表 parent指针&#xff1a; 注意&#xff1a;树结点在 组织链表 中的位置不代表树的任何逻辑关系 树的架构图&#xf…

软件测试|使用Python抓取百度新闻的页面内容

简介 作为技术工程师&#xff0c;在繁忙的工作中我们不一定有时间浏览发生的热点新闻&#xff0c;但是懂技术的我们不需要访问网站来看当下发生的大事&#xff0c;我们可以使用网络爬虫的技术来获取当下最新最热的新闻&#xff0c;本文就来介绍一下使用Python抓取一下百度新闻…

2、Redis持久化、主从与哨兵:构建强大而稳定的数据生态

Redis作为一款高性能的内存数据库&#xff0c;其在持久化、主从复制和哨兵系统方面的支持使其在大规模应用和高可用性场景中脱颖而出。本文将深入探讨Redis的持久化机制、主从复制以及哨兵系统&#xff0c;为构建强大而稳定的数据生态揭示关键技术。 持久化&#xff1a;数据的…

B端产品经理学习-版本规划管理

首先我们回顾一下用户故事&#xff0c;用户故事有如下特点&#xff1a; PRD文档的特点则如下&#xff1a; B端产品中用户角色不同&#xff0c;需求侧重也不同 决策人——公司战略需求&#xff1a;转型升级、降本增效、品牌提升等 管理负责人——公司管理需求&#xff1a;提升…

Kafka详解

KAFKA 1、消息队列&#xff08;了解&#xff09; 1-1 消息队列介绍 英文名&#xff1a;Message Queue&#xff0c;经常缩写为MQ。从字面上来理解&#xff0c;消息队列是用来存储传递消息的 1-2 消息队列应用场景 应用耦合-- 使用消息队列解耦 后端业务开发实名认证 图片上传功…

sectigo ip证书种类买一年送一月

Sectigo旗下的IP证书是专为只有公网IP地址的网站准备的。Sectigo旗下的数字证书大多是域名证书&#xff0c;例如&#xff0c;单域名SSL证书、多域名SSL证书、通配符SSL证书等。这些证书申请时必须验证域名所有权&#xff0c;申请者需要有一个拥有管理全的域名网站&#xff0c;那…

四、C语言中的数组:数组的创建与初始化

其实在之前的学习中我们已经或多或少接触到了数组&#xff0c;有关scanf()的安全用法中我们提到了如何避免数组溢出的问题&#xff0c;详情可以查看二、C语言数据类型与变量&#xff08;scanf和printf (4&#xff09;完) 这一章我们将详细学习数组在C语言中的应用 本章的学习…

MaxKey 单点登录认证系统——实现登录后自动跳转及分析思路

Maxkey单点登录系统集成业务系统应用之后&#xff0c;登录界面登录之后不会自动跳转业务系统&#xff0c;需要在首页点击相应应用之后&#xff0c;才能实现跳转业务系统&#xff0c;故以下本人提供解决方法和分析思路。 环境配置 本例使用的是CAS协议实现单点登录 Maxkey 服务…

优化 - 重构一次Mysql导致服务器的OOM

概述 优化了一次前后端处理不当导致的CPU的一次爆机行为&#xff0c;当然&#xff0c;这和服务器的配置低也有着密不可分的关系&#xff0c;简单的逻辑学告诉我们&#xff0c;要找到真正的问题&#xff0c;进行解决&#xff0c;CPU爆机的关键点在于前后端两个方面&#xff0c;…

POI-tl 知识整理:整理1 -> 利用模板向word中写入数据

1 文本传值 Testpublic void testText() throws Exception {XWPFTemplate template XWPFTemplate.compile("D:\\Idea-projects\\POI_word\\templates.docx");Map<String, Object> map new HashMap<>();map.put("title", "Hi, girl"…

如何在你的网站接入QQ登录?

文章目录 准备阶段申请QQ登录的权限创建应用最后上传qqlogin.php代码 准备阶段 国内服务器和备案域名需要你有张独一无二本人的身份证你正面手持身份证的图片一张100px*100px的网站图标 申请QQ登录的权限 首先访问qq互联&#xff0c;点击我直接访问 登陆完成后我们点击面的…

橘子学Spring01之spring的那些工厂和门面使用

一、Spring的工厂体系 我们先来说一下spring的工厂体系(也称之为容器)&#xff0c;得益于大佬们对于单一职责模式的坚决贯彻&#xff0c;在十几年以来spring的发展路上&#xff0c;扩展出来大量的工厂类&#xff0c;每一个工厂类都承担着自己的功能(其实就是有对应的方法实现)…

(三)CMake为什么几乎一统C++跨平台构建?

先看几个简单的例子再回头来看这个问题 回想一下当我们用windows写C第一个Hello World!的步骤&#xff0c;先用VS IDE 创建一个控制台的工程&#xff0c;IDE 会自动生成一个 cpp 文件&#xff0c;里面有一句 输出"Hello World!" 代码&#xff0c;这个时候按下F5 就可…

PTA 1117 数字之王 C++实现 简易代码

给定两个正整数 N1​<N2​。把从 N1​ 到 N2​ 的每个数的各位数的立方相乘&#xff0c;再将结果的各位数求和&#xff0c;得到一批新的数字&#xff0c;再对这批新的数字重复上述操作&#xff0c;直到所有数字都是 1 位数为止。这时哪个数字最多&#xff0c;哪个就是“数字…

在线直线度测量仪确保了出厂圆棒无不合格品

在线直线度测量仪确保了出厂圆棒无不合格品 随着生产设备的改进&#xff0c;利用基础材料进行生产的厂家对品质要求也越来越高&#xff0c;其中圆形棒管材的直线度尺寸&#xff0c;也是广受关注&#xff0c;对其进行矫直检测&#xff0c;使其出厂无不合格品。 变抽检为全检 以前…

逼格满满,推荐一个高效测试用例工具:XMind2TestCase !

一、背景 软件测试的核心是什么&#xff1f;毫无疑问是测试分析和测试用例设计&#xff0c;也是日常测试投入最多时间的工作内容之一。 然而&#xff0c;传统的测试用例设计过程有很多痛点&#xff1a; 1、使用Excel表格进行测试用例设计&#xff0c;虽然成本低&#xff0c;但…

Java 并发性和多线程3

七、线程安全及不可变性 当多个线程同时访问同一个资源&#xff0c;并且其中的一个或者多个线程对这个资源进行了写操作&#xff0c;才会产生竞态条件。多个线程同时读同一个资源不会产生竞态条件。 我们可以通过创建不可变的共享对象来保证对象在线程间共享时不会被修改&…