链地址法(哈希桶)

链地址法(哈希桶)

解决冲突的思路

开放定址法中所有的元素都放到哈希表⾥,链地址法中所有的数据不再直接存储在哈希表中,哈希表 中存储⼀个指针,没有数据映射这个位置时,这个指针为空,有多个数据映射到这个位置时,我们把这些冲突的数据链接成⼀个链表,挂在哈希表这个位置下⾯,链地址法也叫做拉链法或者哈希桶。

扩容

开放定址法负载因⼦必须⼩于1,链地址法的负载因⼦就没有限制了,可以⼤于1。负载因⼦越⼤,哈 希冲突的概率越⾼,空间利⽤率越⾼;负载因⼦越⼩,哈希冲突的概率越低,空间利⽤率越低;stl中 unordered_xxx的最⼤负载因⼦基本控制在1,⼤于1就扩容,我们下⾯实现也使⽤这个⽅式。

下⾯演⽰ {19,30,5,36,13,20,21,12,24,96} 等这⼀组值映射到M=11的表中

image-20250106214034236

h(19) = 8,h(30) = 8,h(5) = 5,h(36) = 3,h(13) = 2,h(20) = 9,h(21) = 10,h(12) = 1,h(24) = 2,h(96) = 88

在这里插入图片描述

哈希桶实现代码:

namespace hash_bucket
{//仿函数template<class K>struct HashFunc{size_t operator()(const K& key){return (size_t)key;}};//string用得多,特化一下template<>struct HashFunc<string>{size_t operator()(const string& s){size_t hash = 0;for (auto ch : s){hash += ch;}return hash;}};template<class K,class V>struct HashNode{pair<K, V> _kv;HashNode<K, V>* _next;//别定义成pair了HashNode(const pair<K,V>& kv):_kv(kv),_next(nullptr){}};template<class K,class V,class Hash=HashFunc<K>> class HashTable{typedef HashNode<K, V> Node;public:HashTable():_tables(__stl_next_prime(0)),_n(0){}//vector里面存的是内置类型Node*而不是自定义类型,所以要自己处理//如果析构需要自己写那么拷贝构造和赋值重载也得自己写~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;//}}Hash hash;//Node* Find(const K& key){size_t hashi = hash(key) % _tables.size();Node* cur = _tables[hashi];while (cur){if (key == cur->_kv.first){return cur;}cur = cur->_next;}return nullptr;}bool Erase(const K& key){size_t hashi = hash(key) % _tables.size();Node* cur = _tables[hashi];Node* prev = nullptr;//要记录while (cur){if (key == cur->_kv.first){//分两种情况处理if (prev == nullptr)//要删除的是头结点{_tables[hashi] = cur->_next;}else//删除的不是头结点{prev->_next = cur->_next;}delete cur;--_n;return true;}prev = cur;cur = cur->_next;}return false;}bool Insert(const pair<K,V>& kv){if (_n == _tables.size()){vector<Node*> newtables(__stl_next_prime(_tables.size())+1);for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;size_t hashi = hash(cur->_kv.first) % newtables.size();cur->_next = newtables[hashi];newtables[hashi] = cur;cur = next;}_tables[i] = nullptr;}_tables.swap(newtables);//}//头插size_t hashi = hash(kv.first) % _tables.size();Node* newnode = new Node(kv);newnode->_next = _tables[hashi];_tables[hashi] = newnode;++_n;return true;}private:vector<Node*> _tables;size_t _n=0;//自己造轮子/*struct Data{ListNode* _head;RBTreeNode* _root;size_t len;};*///套两个结构在里面/*struct Date{list<pair<K, V>> _list;map<pair<K, V>> _map;size_t len;};vector<Data> _tables;size_t _n = 0;*/};

Tips:

  • 在扩容时,我们不再像开放定址法为了复用Insert而创建一个HashTable而是创建一个新vector,因为Insert里要创建新节点,然后swap之后带走旧表时又要释放这些结点,一来一回消耗比较大;直接用新vector,把原vector挂的结点直接“拿”到新表就可以了。
  • 如果觉得挂的链表太长了,可以换成比如_n>8就换挂红黑树,创建一个结构体Data,里面存储的可以是自己“造轮子”的也可以直接用list和map这两个结构(就可以直接用自带的接口)。如果减到比如8个以下了再换回链表。
  • vector里面存的是内置类型Node*而不是自定义类型,所以要自己处理,否则不会被处理;如果析构函数需要自己实现,那么赋值重载和拷贝构造也需要自己实现,深拷贝。

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

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

相关文章

【C语言】可移植性陷阱与缺陷(七): 除法运算时发生的截断

在C语言编程中&#xff0c;除法运算可能会引发一些与可移植性相关的问题&#xff0c;特别是当涉及到整数除法时发生的截断&#xff08;truncation&#xff09;。不同平台对于整数除法的行为和处理方式可能会有所不同&#xff0c;这可能导致代码在不同编译器或硬件平台上的行为不…

2. 模型和算法

1. 模型&#xff08;Model&#xff09; 模型指的是通过机器学习或其他方法从数据中提取出的一个数学结构或表示&#xff0c;它可以用于做出预测、分类、回归或其他决策任务。模型是机器学习的核心&#xff0c;它在一定程度上是数据的“抽象化”&#xff0c;用于表达输入与输出…

C++ 原子变量

C 原子变量 文章目录 C 原子变量1. 原子变量是什么&#xff1f;2. 原子操作的特点3. 原子变量的作用1. 多线程安全的共享数据访问2. 替代锁机制3. 实现低级同步算法 4. 原子变量的常见操作5. 内存顺序&#xff08;Memory Ordering&#xff09;内存顺序控制在原子变量中的作用如…

前后端分离架构设计与实现:构建现代Web应用的基石

前后端分离架构设计与实现&#xff1a;构建现代Web应用的基石 引言 随着互联网技术的发展&#xff0c;Web应用变得越来越复杂和多样化。传统的单体式架构难以满足快速迭代、团队协作以及性能优化的需求。前后端分离架构应运而生&#xff0c;它不仅提高了开发效率&#xff0c;…

了解RabbitMQ的工作原理

RabbitMQ是一个开源的消息代理系统&#xff0c;实现了高级消息队列协议&#xff08;AMQP&#xff09;。在现代分布式系统中&#xff0c;特别是在微服务架构中&#xff0c;RabbitMQ有广泛的应用。本文将详细介绍RabbitMQ的工作原理&#xff0c;并通过实践案例帮助读者理解和应用…

Excel中公式和函数的区别

Excel中公式和函数的区别 概念讲解例子公式函数 详细介绍函数面板最后再次进行演示操作文档 概念讲解 公式是用户自己编写的表达式&#xff0c;而函数是由Excel预定义的操作。公式可以包含各种数学运算符和逻辑表达式&#xff0c;函数则是执行特定任务的工具。公式可以引用其他…

分布式搜索引擎之elasticsearch基本使用3

分布式搜索引擎之elasticsearch基本使用3 1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像&…

【FlutterDart】 拖动改变 widget 的窗口尺寸大小GestureDetector~简单实现(10 /100)

上效果 预期的是通过拖动一条边界线改变窗口大小&#xff0c;类似vscode里拖动效果。这个是简单的拖动实现 上代码&#xff1a; import package:flutter/material.dart;class MyDraggableViewDemo extends StatelessWidget {const MyDraggableViewDemo({super.key});override…

使用Dinky快速提交Flink operator任务

官网地址&#xff1a;K8s集成 | Dinky 1.目前使用版本 Dinky1.2.0、Flink1.18.1、Flink operator0.10.0 2.制作镜像 2.1创建DockerFile ARG FLINK_VERSION1.18.1 FROM flink:${FLINK_VERSION}-scala_2.12 RUN mkdir -p /opt/flink/usrlib COPY commons-cli-1.3.1.jar …

查找路由器的管理后台ip【通用找IP】

需求&#xff1a; 刚刚搞了个【小米】路由器&#xff0c;我想进路由的管理后台&#xff0c;提示&#xff1a;安装xx的路由管家&#xff0c;我不想安装 但是无法找到这个管理后台。 而且我是用这个路由作为中继&#xff0c;那么这个路由的ip就会经常更换 尝试通过网上搜索引擎来…

【大数据】(选修)实验4 安装熟悉HBase数据库并实践

实验4 安装熟悉HBase数据库并实践 1、实验目的 (1)理解HBase在Hadoop体系结构中的角色; (2)熟练使用HBase操作常用的Shell命令; (3)熟悉HBase操作常用的Java API。 2、实验平台 操作系统:Linux Hadoop版本:2.6.0或以上版本 HBase版本:1.1.2或以上版本 JDK版…

Flutter鸿蒙化 在鸿蒙应用中添加Flutter页面

前言 今天这节课我们讲一下 在鸿蒙应用中添加Flutter页面。 作用: 之前有很多朋友和网友问我鸿蒙能不能使用Flutter开发,他们的项目已经用Flutter开发成熟了有什么好的方案呢,今天讲到这个就可以很好的解决他们的问题,例如我们正式项目中可能是一部分native 开发 一部分…

vue3-watchEffect异步依赖收集

当 b 更新时 a 并不会更新&#xff0c;因为watchEffect的依赖收集在该案例中停止于await asyncFn()&#xff0c;也就是只会收集同步代码的依赖&#xff0c;await 之后的异步代码的依赖并不会收集到 <template> <div>a: {{ a }} <br>b: {{ b }} <br>&l…

【通识安全】煤气中毒急救的处置

1.煤气中毒的主要症状与体征一氧化碳中毒&#xff0c;其中毒症状一般分为轻、中、重三种。 (1)轻度&#xff1a;仅有头晕、头痛、眼花、心慌、胸闷、恶心等症状。如迅速打开门窗&#xff0c;或将病人移出中毒环境&#xff0c;使之吸入新鲜空气和休息&#xff0c;给些热饮料&am…

【UI自动化测试】selenium八种定位方式

&#x1f3e1;个人主页&#xff1a;謬熙&#xff0c;欢迎各位大佬到访❤️❤️❤️~ &#x1f472;个人简介&#xff1a;本人编程小白&#xff0c;正在学习互联网求职知识…… 如果您觉得本文对您有帮助的话&#xff0c;记得点赞&#x1f44d;、收藏⭐️、评论&#x1f4ac;&am…

redis各种数据类型介绍

Redis 是一种高性能的键值存储数据库&#xff0c;它支持多种数据类型&#xff0c;使得开发者可以灵活地存储和操作数据。以下是 Redis 支持的主要数据类型及其介绍&#xff1a; 1. 字符串&#xff08;String&#xff09; 字符串是 Redis 中最基本的数据类型&#xff0c;它可以存…

【Linux】Linux命令

目录 ​编辑 系统维护命令 man man&#xff1a;查看 man 手册 sudo passwd 用户名&#xff1a;修改用户密码 su&#xff1a;切换用户 echo ”输出内容“&#xff1a;向终端输出内容&#xff0c;默认换行 date查看当前系统的日期 clear&#xff1a;清屏 df -Th /df -h&…

关机重启后,GitLab服务异常

整理机房,关闭了所有主机重新上架。 上架后开机,所有主机硬件启动正常。 其中一台GitLab服务器启动正常,使用gitlab-ctl status查看服务业正常。 但使用web登陆却失败,如下图: 反复测试,发现无论使用正确密码还是错误密码都是同样的提示。很大可能是数据库的问题。 使…

【嵌入式硬件】直流电机驱动相关

项目场景&#xff1a; 驱动履带车&#xff08;双直流电机&#xff09;前进、后退、转弯 问题描述 电机驱动MOS管烧毁 电机驱动采用IR2104STRH1R403NL的H桥方案&#xff08;这是修改之后的图&#xff09; 原因分析&#xff1a; 1.主要原因是4路PWM没有限幅&#xff0c;修改…

Python编程实例-特征向量与特征值编程实现

特征向量与特征值编程实现 文章目录 特征向量与特征值编程实现1、什么是特征向量2、特征向量背后的直觉3、为什么特征向量很重要?4、如何计算特征向量?4、特征向量Python实现5、可视化特征向量6、总结线性代数是许多高级数学概念的基石,广泛应用于数据科学、机器学习、计算机…