[C++][数据结构]哈希2:开散列/哈希桶的介绍和简单实现

前言

接着上一篇文章,我们知道了闭散列的弊端是空间利用率比较低,希望今天学习的开散列可以帮我们解决这个问题

引入

开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址**,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。**

实现

基本结构

template<class K, class V>
struct HashNode
{HashNode<K, V>* _next;pair<K, V> _kv;
};
template<class K,class V>
class HashTable
{using Node = HashNode<K, V>;public://构造HashTable(size_t size = 10){_tables.resize(size, nullptr);_n = 0;}//析构~HashTable(){for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;delete cur;cur = next;}_tables[i] = nullptr;}}private:vector<Node*> _tables;size_t _n = 0;
}

插入

在这里插入图片描述

这就是头插

		bool Insert(const pair<K, V>& kv){size_t hashi = kv.first % _tables.size();	//找到关键码Node* newnode = new Node(kv);				//创建新节点newnode->_next = _tables[hashi];			//先链接上_tables[hashi] = nuwnode;					//再更新头节点}

扩容

(可以参考set和map的扩容,都使用了提供的swap函数)

			if (_n == _tables.size()){vector<Node*> newTable(_tables.size() * 2, nullptr);for (size_t i = 0; i < _tables.size(); i++){//遍历旧表,重新计算Node* cur = _tables[i];while (cur){Node* next = cur->_next;size_t hashi = cur->_kv, first% newTable.size();cur->_next = newTable[hashi];newTable[hashi] = cur;cur = next;}tables[i] = nullptr;}_tables.swap(newTables);}//扩容机制

删除

删除,删的是_key是key的这个桶,

返回值:
可以是bool也可以是下一个桶的指针

		bool Erase(const K& key){Hash hs;																//取出key的value值,//可以是仿函数、lambda,看传入的是什么size_t hashi = hs(key) % _tables.size();Node* prev = nullptr;Node* cur = _tables[hashi];while (cur){if (cur->_kv.first == key)//满足条件{// 删除if (prev){prev->_next = cur->_next;}else{_tables[hashi] = cur->_next;}delete cur;--_n;//桶个数--return true;}prev = cur;cur = cur->_next;}return false;}

对各项的检查函数

		void Some(){size_t bucketSize = 0;size_t maxBucketLen = 0;size_t sum = 0;double averageBucketLen = 0;for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];if (cur){++bucketSize;}size_t bucketLen = 0;while (cur){++bucketLen;cur = cur->_next;}sum += bucketLen;if (bucketLen > maxBucketLen){maxBucketLen = bucketLen;}}averageBucketLen = (double)sum / (double)bucketSize;printf("load factor:%lf\n", (double)_n/ _tables.size());//负载因子printf("all bucketSize:%d\n", _tables.size());//桶的个数printf("bucketSize:%d\n", bucketSize);printf("maxBucketLen:%d\n", maxBucketLen);//桶的最大值printf("averageBucketLen:%lf\n\n", averageBucketLen);//桶的平均大小}

补充

当某个桶数据过多时,我们可以把这个桶指向的节点变成红黑树,但什么时候变目前不去考虑

结语

文章写到这里有点戛然而止的感觉,不过本文主要是为了介绍概念、只实现了插入和删除。

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

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

相关文章

CMainFrame的OnCreate()函数

在MFC&#xff08;Microsoft Foundation Classes&#xff09;框架中&#xff0c;CMainFrame类通常代表应用程序的主框架窗口。OnCreate()函数是一个非常重要的成员函数&#xff0c;其主要职责是响应WM_CREATE消息。当窗口开始创建时&#xff0c;操作系统会发送这个消息。因此&a…

latex algorithm2e 库学习总结

案例1 \documentclass{article}\usepackage{xeCJK} \usepackage[]{algorithm2e} %\usepackage{ctex} % 中文包\begin{document}\renewcommand{\algorithmcfname}{算法} % 把标题设置为“算法” \begin{algorithm…

离线维护麒麟操作系统

1 本地源设置 a 首先传输一个镜像ISO文件到离线系统。 b 加载镜像文件作为源文件。 #mkdir /mnt/cdrom #mount -o path/镜像.iso /mnt/cdromc 修改源文件 # cd /etc/yum.repo.d/ # vi base.repo 修改baseurl file:///mnt/cdrom d update &install 然后就可以愉快的…

云衔科技成为卓豪Zoho中国区代理商,开启智能化企业管理新篇章

每一家企业数字化转型&#xff0c;都在寻求通过技术创新实现业务的飞跃。为了更好地服务于中国企业的数字化转型需求&#xff0c;云衔科技荣幸宣布正式成为卓豪Zoho中国区代理商&#xff0c;这一强强联合将为市场带来全新的数字化解决方案与服务体验&#xff0c;共同开启中国企…

【代码随想录37期】Day02 有序数组的平方、长度最小的子数组、螺旋矩阵Ⅱ(施工中)

有序数组的平方 977. 有序数组的平方 - 力扣&#xff08;LeetCode&#xff09; v1.0:直接暴力 4分半做出来&#xff0c;用sort api class Solution { public:vector<int> sortedSquares(vector<int>& nums) {vector<int> result;for(int i 0; i<…

鲁教版六年级数学上册-笔记

文章目录 第一章 丰富的图形世界1 生活中的立体图形2 展开和折叠3 截一个几何体4 从三个方向看物体的形状 第二章 有理数及其运算1 有理数2 数轴3 绝对值4 有理数的加法5 有理数的减法6 有理数的加减混合运算7 有理数的乘法8 有理数的除法9 有理数的乘方10 科学计数法11 有理数…

顺序表经典算法OJ题-- 力扣27,88

题1&#xff1a; 移除元素 题2&#xff1a; 合并两个有序数组 一&#xff1a;题目链接&#xff1a;. - 力扣&#xff08;LetCode&#xff09; 思路&#xff1a;&#xff08;双指针法&#xff09; 创建两个变量src&#xff0c;dst 1&#xff09;若src指向的值为val&#xf…

leetcode-字符串的排列-100

题目要求 思路 1.因为只涉及到字符&#xff0c;因此可以进行排序 2.创建临时字符串&#xff0c;当临时字符串temp的长度等于str的长度&#xff0c;作为判出条件。 3.创建一个标记的数组&#xff0c;每次在temp中插入一个字符&#xff0c;便在对应的数组下标设置为1&#xff0c…

国内如何访问 OpenAI 的 api

这个问题甚至我的一些大厂的朋友也不太清楚&#xff0c;所以我觉得有必备写一篇文章来简单盘盘它&#xff0c;希望能帮助到有需要的人 众所周知&#xff0c;由于大陆与 OpenAI 双方互相封锁&#xff0c;大陆是无法直接访问 OpenAI api 的 不过由于 GPT 4 的统治地位&#xff0c…

C++|二叉搜索树

一、二叉搜索树的概念 二叉搜索树又称为二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有节点的值小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根结…

人工智能绘图工具与设计师的未来发展

随着人工智能技术的不断进步和应用&#xff0c;AI绘图工具如Midjourney等在设计领域的出现引发了广泛的关注和讨论。这些工具号称可以让没有美术基础的人也能快速上手制作出漂亮的图像&#xff0c;给设计师们带来了一些担忧和不确定性。有人担心AI绘图工具会取代设计师的工作&a…

Obsidian 下载安装和运行

1 官网页面 2 Github 页面 3 选择合适的版本&#xff0c;下载后运行。 附录&#xff1a; 官网&#xff1a; https://obsidian.md/ Github 地址&#xff1a; https://github.com/obsidianmd/obsidian-releases/releases 参考&#xff1a; Markdown 官方教程 https://markdow…

2024 年 数维杯(B题)大学生数学建模挑战赛 | 生物质和煤共热解 | 数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 CS团队倾注了大量时间和心血&#xff0c;深入挖掘解决方案。通…

什么是FMEA的分析范围?——FMEA软件

免费试用FMEA软件-免费版-SunFMEA FMEA的分析范围广泛而深入&#xff0c;涵盖了产品设计、制造过程、供应链管理以及使用和维修等多个方面。 产品设计是FMEA分析的重要一环。在设计阶段&#xff0c;FMEA能够帮助工程师识别潜在的设计缺陷&#xff0c;并预测这些缺陷可能对产品…

产品激光安全相关知识总结

平时消费产品涉及的激光安全知识讲解 文章目录 平时消费产品涉及的激光安全知识讲解一.**智能时代下的激光产品现状**1.1 手机 人脸识别用的激光1.2 智能门锁 人脸识别用的激光/人体检测用的dtof点激光1.3 扫地机 前置避障用的线激光/三角测距雷达发射的点激光/DTOF雷达发射的点…

《CKA/CKAD应试指南/从docker到kubernetes 完全攻略》学习笔记 第13章 网络管理

目录 前言 13.1 实验准备 13.2 创建ingress类型的网络策略 13.2.1 允许特定标签的pod能访问 <

【系统架构师】-案例篇(七)信息安全

某软件公司拟开发一套信息安全支撑平台&#xff0c;为客户的局域网业务环境提供信息安全保护。该支撑平台的主要需求如下&#xff1a; 1.为局域网业务环境提供用户身份鉴别与资源访问授权功能&#xff1b; 2.为局域网环境中交换的网络数据提供加密保护&#xff1b; 3.为服务…

SpringBoot web项目性能监控

新增两个接口&#xff1a;jmap 和 jstack&#xff0c;用于获取 Java 应用程序的内存堆转储&#xff08;heap dump&#xff09;和线程转储&#xff08;thread dump&#xff09;。 添加依赖&#xff1a; implementation("commons-io:commons-io:2.11.0") 添加control…

LeetCode刷题笔记第1480题:一维数组的动态和

LeetCode刷题笔记第1480题&#xff1a;一维数组的动态和 题目&#xff1a; 给你一个数组 nums 。数组「动态和」的计算公式为&#xff1a;runningSum[i] sum(nums[0]…nums[i]) 。 请返回 nums 的动态和。 想法&#xff1a; 想要计算数组每个位置上的动态和&#xff0c;利…

C#常用关键字 收藏集

out 作为参数修饰符&#xff0c;它允许按引用而不是按值向方法传递参数。接口和委托的泛型类型参数声明中&#xff0c;该声明指定类型参数为协变。 public void Main(){double radiusValue 3.92781;//计算圆的周长和面积&#xff0c;并将结果返回给 Main().CalculateCircumf…