[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,一经查实,立即删除!

相关文章

latex algorithm2e 库学习总结

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

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

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

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

文章目录 第一章 丰富的图形世界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;则右子树上所有节点的值都大于根结…

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;并预测这些缺陷可能对产品…

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

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

综述列表(~2024.05.10)

&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 每周末更新&#xff0c;完整版进群获取。 Q 群在群文件&#xff0c;VX 群每周末更新。

多线程-写入读取文件,使用同步逻辑

在一个进程中&#xff0c;创建一个子线程。 主线程负责:向文件中写入数据 子线程负责:从文件中读取数据 要求使用线程的同步逻辑&#xff0c;保证一定在主线程向文件中写入数据成功之后&#xff0c;子线程才开始运行&#xff0c;去读取文件中的数据 #include <stdio.h> …

Linux0.11中MINIX 文件系统

阅读linux 的源码的时候对minix 文件系统有很多的疑惑&#xff0c;根据自己的认识将这些做一个总结。 MINIX 文件系统由六个部分组成&#xff0c;分别是引导块&#xff0c;超级块&#xff0c;i结点位图&#xff0c;逻辑块位图&#xff0c;i结点&#xff0c;数据块。 引导块&am…

部署xwiki服务需要配置 hibernate.cfg.xml如何配置?

1. 定位 hibernate.cfg.xml 文件 首先&#xff0c;确保您可以在 Tomcat 的 XWiki 部署目录中找到 hibernate.cfg.xml 文件&#xff1a; cd /opt/tomcat/latest/webapps/xwiki/WEB-INF ls -l hibernate.cfg.xml如果文件存在&#xff0c;您可以继续编辑它。如果不存在&#xff…

使用GitLab自带的CI/CD功能在远程服务器部署项目(三)

前置内容&#xff1a; 通过Docker Compose部署GitLab和GitLab Runner&#xff08;一&#xff09; 使用GitLab自带的CI/CD功能在本地部署项目&#xff08;二&#xff09; 目录 一、在GitLab服务器上生成私钥与公钥 二、将公钥拷贝到应用服务器上 三、将私钥给到Docker Exec…

深入解析Java中Set接口

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

数据驱动实战二

目标 掌握数据驱动的开发流程掌握如何读取JSON数据文件巩固PO模式 1. 案例 对TPshop网站的登录模块进行单元测试 1.1 实现步骤 编写测试用例采用PO模式的分层思想对页面进行封装编写测试脚本定义数据文件&#xff0c;实现参数化 1.2 用例设计 1.3 数据文件 {"login…

设置LCD为第二终端

我一直使用xshell端&#xff0c;开发板通过串口和 xshell进行通信。 调试好LCD 驱动之后&#xff0c;可以设置 LCD 作为终端&#xff0c;也就是开发板使用自己的显示 设备作为自己的终端&#xff0c;然后接上键盘就可以直接在开发板上敲命令了&#xff0c;将 LCD 设置为终端控制…

Linux(利用gdb进行调试)

gdb: gdb是GNU debugger的缩写&#xff0c;是编程调试工具。 gdb功能 1.启动程序&#xff0c;可以按照用户自定义的要求随心所欲的运行程序。 2.让被调试的程序在用户所指定的调试的断点处停住 (断点可以是条件表达式)。 3.当程序停住时&#xff0c;可以检查此时程序中所发…