哈希桶的增删查改简单实现

news2024/12/23 21:00:13

个人简单笔记。

目录

闭散列

开散列

插入

删除

查找

改变


什么是哈希桶呢?这是一个解决哈希数据结构的一种解决方法,在STL中的unorder_map与unorder_set的底层结构就是使用它来实现的。

闭散列

首先我们知道,哈希映射表是依据数组下标数据的。

 这时候然后如果来了映射值数据为0的数据,检测发现0位置已经被30占用,需要线性探测后面的空位置,就存入数据,这就叫做哈希冲突。

这样看似非常方便,但是有一个非常不好的地方那就是将其他位置给占用了,这样如果存储了其他数据连带一片的冲突产生:让我们看下图。

 我们1将下标1的位置占用了,那么11、21、31使用了依次占用后面空间位置。进入进数据

映射1的数据他们的连带将2,3,4下标位置映射给占用了,导致22、3、14第一次映射位置就发生哈希冲突,并且这3个数据也占用了下标5、6、7位置,造成一大片哈希冲突,极其影响数据增删查改。所以我们的必须改变哈希结构,使用开散列的方法。

开散列

开散列又名哈希桶、开链法。

我们的数据存放的不再是单纯存放数据到数组中,还记得我们的链表吗?我们的哈希表中存放的就是一个一个的链表的头节点数据。

 这时候我们再将数据存放入表中。

这时候映射到1的数据,自己冲突自己的,不影响其他下标位置,这就是我们的哈希桶模型。

插入

先映射寻找链表首端,再就是普通的链表插入。需要注意尾插的第一个插入或者头删的

bool insert(const pair<K, V>& kv)
{
	//哈希桶的负载因子为1
	if (_size + 1 > _tables.size())
	{
		//扩容逻辑
		Hash hash;
		size_t newsize = _tables.size() == 0 ? 10 : _tables.size() * 2;
		vector<Node*>newTables;//我们的开散列不能去像闭散列一样创建新对象插入,
		//我们需要的是重新创建的是数组表,将一个个node
		//重新链接到新数组表中,避免需要一直重新创建结点。
		newTables.resize(newsize);
		//old表node移动到new表
		//为了不浪费
		for (size_t i = 0; i < _tables.size(); ++i)
		{
			Node* cur = _tables[i];//原表的每个元素都给cur
			while (cur)
			{
				Node* oldnext = cur->_next;//记录原表当前结点的下一个
				size_t index = hash(cur->_kv.first) % newTables.size();
				cur->_next = newTables[index];//这里采用的是头插。
				newTables[index] = cur;
				cur = oldnext;//迭代
			}
			_tables[i] = nullptr;//置空原表,没必要但是好习惯
		}
		newTables.swap(_tables);//交换old与new表,完成扩容
	}

	Hash hash;//仿函数
	size_t index = hash(kv.first) % (_tables.size());
	//头插
	if (Find(kv.first))
	{
		return false;
	}
	Node* newnode = new Node(kv);
	newnode->_next = _tables[index];
	_tables[index] = newnode;
	//尾插
	/*Node* newnode = new Node(kv);
	if (_tables[index] == nullptr)
	{
		_tables[index] = newnode;
	}
	else
	{
		Node* cur = _tables[index];
		Node*prev = _tables[index];
		while (cur)
		{
			if (cur->_kv == kv)
			{
				delete newnode;//如果发现已经存在我们需要delete新结点,防止内存泄漏
				return false;
			}
			prev = cur;
			cur = cur->_next;
		}
		prev->_next = newnode;
	}*/
	_size++;//数据加一
	return true;
}

删除

bool Erese(const K& key)
{
	if (_tables.size() == 0)//防止除0
	{
		return false;
	}
	Hash hash;
	size_t index = hash(key) % (_tables.size());
	Node* cur = _tables[index];//简单的链表删除
	Node* prev = cur;
	while (cur)
	{
		if (cur->_kv.first == key)
		{
			if (cur == _tables[index])//如果就是删除链表头结点
			{
				_tables[index] = cur->_next;
			}
			else//非头节点删除
			{
				prev->_next = cur->_next;
			}
			delete cur;
			_size--;
			return true;
		}
		prev = cur;//迭代
		cur = cur->_next;
	}
	return false;
}

查找

Node* Find(const K& key)
{
	if (_tables.size() == 0)//防止除0
	{
		return nullptr;
	}
	Hash hash;
	size_t index = hash(key) % (_tables.size());//找头节点位置
	Node* cur = _tables[index];//普通的单链表查找
	while (cur)
	{
		if (cur->_kv.first == key)//找到了
		{
			return cur;
		}
		cur = cur->_next;
	}
	return nullptr;//没找到
}

改变

bool change(const K& key, const V& val)
{
	Node* ret = Find(key);//查找位置
	if (!ret)//没找到返回
	{
		return false;
	}
	else//找到改变返回
	{
		ret->_kv.second = val;
		return true;
	}
}

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

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

相关文章

CSS画特殊边框

例如如图所示边框 .card-middle {width: 672px;height: 486px;border: 1px solid #5fadec;border-radius: 5px;position: relative; }.card-middle::before {content: ;position: absolute;top: -4px;left: -4px;width: 680px;height: 448px;border: 25px solid transparent;b…

【Python】PIL.Image转QPixmap后运行异常的个人解决方法

问题场景&#xff1a; PIL.Image图片&#xff0c;直接调用PIL.Image.toqpixmap()转成QPixmap后&#xff0c;不会立即报错&#xff0c;   但后续使用该QPixmap时(包括但不仅限于使用QLabel.setPximap()、QPixmap.save())将立即出现异常 不知道是我关键词不对&#xff0c;还是只…

【数据结构与算法】文学语言助手(C\C++)

实践要求 1. 问题描述 文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。试写一个实现这一目标的文字统计系统&#xff0c;称为"文学研究助手"。 2. 基本要求 英文小说存于文本文件中。待统计的词汇集合要一次输入完毕&#xff0c;即统计工作必需在…

linux常用命令介绍 06 篇——Linux查看目录层级结构以及创建不同情况的层级目录

linux常用命令介绍 06 篇——Linux查看目录层级结构以及创建不同情况的层级目录 1. 前言1.1 Linux常用命令其他篇1.2 关于tree简介 2. 安装并使用 tree2.1 安装tree2.1.1 方式1&#xff1a;yum安装2.1.2 方式2&#xff1a;下载安装包安装2.1.2.1 下载安装包2.1.2.2 解压安装2.1…

transformer入坑指南

*免责声明: 1\此方法仅提供参考 2\搬了其他博主的操作方法,以贴上路径. 3* 场景一: Attention is all you need 场景二: VIT 场景三: Swin v1 场景四: Swin v2 场景五: SETR 场景六: TransUNet 场景七: SegFormer 场景八: PVT 场景九: Segmeter … 场景一:Attention…

Spring Boot 中的 Spring Cloud Ribbon:什么是它,原理及如何使用

Spring Boot 中的 Spring Cloud Ribbon&#xff1a;什么是它&#xff0c;原理及如何使用 在分布式系统中&#xff0c;服务之间的通信是非常重要的。在大型的分布式系统中&#xff0c;有许多服务需要相互通信&#xff0c;而这些服务可能会部署在多个服务器上。为了实现服务之间…

超详细Redis入门教程——Redis分布式系统

前言 本文小新为大家带来 Redis分布式系统 相关知识&#xff0c;具体内容包括数据分区算法&#xff08;包括&#xff1a;顺序分区&#xff0c;哈希分区&#xff09;&#xff0c;系统搭建与运行&#xff08;包括&#xff1a;系统搭建&#xff0c;系统启动与关闭&#xff09;&…

把 OpenGrok search 上的Android 开源代码扒下来

1、下载工具 wget &#xff08;window10版本&#xff09;以及配置环境变量 工具我会上传到本篇博客的“代码包”区域&#xff0c;可以自行下载&#xff01; 当然如果可以访问如下链接的话&#xff0c;也可以在这个地址自行下载一个比较新的版本即可&#xff01;GNU Wget 1.21.…

Web服务器群集:LVS+Keepalived高可用群集

目录 一、理论 1.Keepalived 2.VRRP协议&#xff08;虚拟路由冗余协议&#xff09; 3.部署LVSKeepalived 高可用群集 二、实验 1.LVSKeepalived 高可用群集 三、问题 1.备服务器网卡启动报错 四、总结 一、理论 1.Keepalived &#xff08;1&#xff09;简介 Keepal…

【动态规划算法】-第一题:1137.第N个斐波那契数

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树 &#x1f389;作者宣言&#xff1a;认真写好每一篇博客 &#x1f38a;作者gitee:gitee 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; 文章目录 前言 前言 各位友友们&#xff0c…

element之el-table合并列功能

目标效果如下&#xff1a; 实现代码如下&#xff1a; html部分&#xff1a; <!--定义表格组件,用组件自带的span-method属性定义合并列的方法--> <el-table :data"tableData" :span-method"spanRow"><el-table-column prop"RegionNa…

在proteus中仿真arduino驱动点阵屏matrix-led

我们都知道&#xff0c;如果我们仅仅在某个时间段点亮一个数码管是没有任何困难的&#xff0c;但如果我们点亮多个数码管就会出现问题&#xff0c;因为多个数码管都使用着同样的端口来控制数码管的各个段的亮灭。所以&#xff0c;就会用上一个很重要的方法&#xff0c;对&#…

使用javaScript脚本生成openFoam网格

简介 OpenFoam的首选网格生成器是blockMesh。blockMesh可以根据blockMeshDict这个字典中的信息生成openFoam网格。但是有时候需要修改网格&#xff0c;而网格中的几何点之间又存在约束关系&#xff0c;如果手动修改blockMeshDict那么工作量将是巨大的&#xff0c;所以有必要使…

有没有免费提取音频的软件,分享几个给大家!

在日常生活中&#xff0c;我们经常遇到需要从视频中提取音频的情况&#xff0c;无论是为了制作音频片段、录制语音笔记还是进行后期编辑。本文将介绍三种免费提取音频的方法&#xff0c;分别是记灵在线工具、PR&#xff08;Adobe Premiere Pro&#xff09;和剪映。通过这些方法…

【Vue3】学习笔记-自定义hook函数

概念 什么是hook? 本质是一个函数&#xff0c;把setup函数中使用的Composition API进行了封装。 类似于vue2.x中的mixin。(但是mixins会组件的配置项覆盖。vue3使用了自定义hooks替代mixnins&#xff0c;hooks本质上是函数&#xff0c;引入调用。) 自定义hook的优势: 复用代…

PPU (power policy unit)

写在前边 最近在做低功耗验证&#xff0c;项目中涉及到PPU这一块儿&#xff0c;在家查了好久资料&#xff0c;发现能找到的有价值的文章真的好少&#xff0c;机缘巧合之下&#xff0c;让我找到下边总结&#xff0c;分享出来&#xff0c;希望对和我有相同境遇的小伙伴带来帮助&a…

每周学点数学 2:概率论基础1

泊松分布、正态分布、二项分布 文章目录 1.概率论学习中的重难点2.主要工具介绍1. Python2. MATLAB3. R4. Octave5. Microsoft Excel6. 统计软件 3.理论内容概览&#xff08;前两点&#xff09;1. 概率2. 概率分布 注&#xff1a;本文适用于在在数学建模的应用中&#xff0c;回…

牛客网基础语法101~110题

牛客网基础语法101~110题&#x1f618;&#x1f618;&#x1f618; &#x1f4ab;前言&#xff1a;今天是咱们第十期刷牛客网上的题目。 &#x1f4ab;目标&#xff1a;对打印图案做到有手就行。 &#x1f4ab;鸡汤&#xff1a;与其花时间应付以后不理想的生活&#xff0c;不如…

学习c++ Part02

学习c Part02 前言1.函数注意点&#xff1a;全局函数&#xff08;默认函数&#xff09;静态函数 2.预处理2.1 变量 3.头文件4.宏函数5.指针5.1 普通变量与指针变量建立关系&#xff1a;5.2 指针初始化5.3 指针变量的注意事项5.3.1 void 不能定义普通变量,void * 可以定义指针变…

SpringBoot源码解析

1.Spring Boot介绍,源码阅读环境搭建,插件安装 2.spring boot 源码解析2-SpringApplication初始化 3.spring boot 源码解析3-SpringApplication#run 4.spring boot 源码解析4-SpringApplication#run第4步 5.spring boot 源码解析5-SpringApplication#run第5步 6.spring boot 源…