哈希表(开散列)的实现

目录

引入

 开散列的底层实现

哈希表的定义

哈希表的扩容

哈希表的插入

哈希表查找

哈希表的删除


引入

接上一篇,我们使用了闭散列的方法解决了哈希冲突,此篇文章将会使用开散列的方式解决哈希冲突,后面对unordered_set和unordered_map的封装也会用开散列的哈希表实现。

开散列,也叫哈希桶和拉链法,其数组中存储的不再是单个数据,而是一个个的节点指针。通过将数据映射到对应位置后,插入到链表中去。

闭散列就像一个个的链表挂在数组上。 


 开散列的底层实现

与闭散列不同的是,开散列哈希表中存储的是节点,不再是具体数据;也不许需要再存储状态,只需要存储下一个指针即可。

哈希表的定义

template<class K,class V>
struct HashNode
{//默认构造HashNode(const pair<K,V>& kv=pair()):_kv(kv),next(nullptr){ }pair<K, V> _kv;HashNode* _next;
};template<class K,class V>
class HashTable
{typedef HashNode<K, V> Node;
public://默认构造HashTable(){_table.resize(10);  //初始情况下数组有10个空间_n = 0;}private:vector<Node*> _table;size_t _n;   //存储有效数据
};

哈希表的扩容

开散列在插入时,像闭散列一样也要检查载荷因子时候满足条件。开散列的载荷因子没有闭散列那么严格,开散列的载荷因子要求小于1即可,平均每条链有一个数据。

在扩容后也需要对数据进行重新插入。

扩容方法:创建新的哈希表,将原数据的节点一个个的插入到新数组中,再将两个数组进行交换。

//扩容
void More()
{if ((double)_n / _table.size() >= 1){//进行扩容HashTable newtable;size_t newsize = 2 * _table.size();newtable._table.resize(newsize);  //扩容两倍扩size_t hashi = 0;while (hashi < _table.size()){if (_table[hashi]){//将数据进行头插Node* pcur = _table[hashi];while (pcur){Node* next = pcur->_next;pcur->_next = newtable._table[hashi];newtable._table[hashi] = pcur;pcur = next;}}hashi++;}_table.swap(newtable._table);}
}

哈希表的插入

//插入
bool insert(const pair<K, V>& kv)
{//扩容More();size_t hashi = kv.first % _table.size();Node* newnode = new Node(kv);//将数据头插到对应映射的位置newnode->_next = _table[hashi];_table[hashi] = newnode;_n++;return true;
}

哈希表查找

先找到映射的位置,在对应位置的链表中查找。

//查找
bool Find(const K& key)
{size_t hashi = key % _table.size();Node* pcur = _table[hashi];while (pcur){if (pcur->_kv.first == key){return true;}pcur = pcur->_next;}return false;
}

哈希表的删除

哈希表的删除比较简单:直接将该节点的前后指针连起来即可。

//删除
bool Erase(const K& key)
{size_t hashi = key % _table.size();Node* pcur = _table[hashi];Node* parent = nullptr;while (pcur){if (pcur->_kv.first == key){if (parent == nullptr){delete pcur;pcur = nullptr;_table[hashi] = nullptr;}else{parent->_next = pcur->_next;delete pcur;}return true;}pcur = pcur->_next;}return false;
}

到此,哈希表的开散列的基本实现已经完成。还有一些具体细节将在《哈希表的封装》中进行具体分析。

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

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

相关文章

机器学习(八):K-Means聚类原理与实战

声明&#xff1a;未经允许禁止转载与抄袭。 前言 k k k均值&#xff08; k k k-means&#xff09;聚类算法是一种经典的无监督聚类算法&#xff0c;本文将深入解析其理论原理&#xff0c;并在真是数据集上进行算法实践&#xff0c;话不多说&#xff0c;请看下文。 算法原理 …

判断矩阵A和矩阵B是否相似?

【例题1】 &#xff08;1&#xff09;方法1 &#xff08;2&#xff09;方法2 &#xff08;3&#xff09;方法3 好题\(^o^)/~ 【注意】当二次多项式有重根时&#xff0c;即判别式为零&#xff0c;此时二次多项式是完全平方。

【10】搭建k8s集群系列(二进制部署)之安装Dashboard和CoreDNS

一、部署Dashboard 1.1、创建kubernetes-dashboard.yaml文件 完整的yaml配置文件信息如下&#xff1a; # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in …

大数据技术与Scala

集合高级函数 过滤 通过条件筛选集合元素&#xff0c;返回新集合。 映射 对每个元素应用函数&#xff0c;生成新集集合 扁平化 将嵌套集合展平为单层集合。 扁平化映射 先映射后展平&#xff0c;常用于拆分字符串。 分组 按规则将元素分组为Map结构。 归约 …

数据驱动可视化实战:图表狐精准生成图表的完整数据范式

一、数据输入黄金法则 图表狐 - AI图表生成工具,在线数据可视化要求数据描述必须包含三个核心要素&#xff1a; [主体对象] [量化指标] [维度划分] 错误示例 ❌&#xff1a; "展示各部门销售额对比" 正确示例 ✅&#xff1a; "2023年Q1-Q4各部门销售额&a…

苍穹外卖(1)-部分环境配置(git、数据库)

首先配置git 创建好本地仓库之后 把项目弄到远程仓库里去 先进行提交 &#xff0c;后进行推送 &#xff0c;然后gitee创建一个仓库 把这个url复制好 推送后会出来一个 点击推送&#xff0c;会让你输入gitee账号密码&#xff0c;输入自己的账号密码&#xff0c;就可以连接远程仓…

Ubunut18.04 离线安装MySQL 5.7.35

一、环境准备 1.1 官方下载MySQL5.7.35 完整包 1.2 上传包 & 解压 上传包名称是&#xff1a;mysql-server_5.7.35-1ubuntu18.04_amd64.deb-bundle.tar # 切换到上传目录 cd /home/MySQL # 解压&#xff1a; tar -xvf mysql-server_5.7.35-1ubuntu18.04_amd64.deb-bundle…

Linux(CentOS10) gcc编译

本例子摘自《鸟哥的linux私房菜-基础学习第四版》 21.3 用make进行宏编译 书中的代码在本机器(版本见下&#xff09;编译出错&#xff0c;改正代码后发布此文章&#xff1a; #kernel version: rootlocalhost:~/testmake# uname -a Linux localhost 6.12.0-65.el10.x86_64 #1…

MCP+Blender创建电力塔

MCP&#xff08;Model Context Protocol&#xff09;与Blender的结合是当前AI与3D建模领域的热门技术&#xff0c;它通过协议化的方式让Claude等AI模型直接控制Blender&#xff0c;实现自动化3D建模。 1. 功能与原理 • 核心能力&#xff1a;用户通过自然语言指令&#xff08;…

Qt与C++数据类型转换

本文深入探讨Qt与C中相似但不同的数据类型处理技巧。 一、QString与std::string的相互转换 1. QString → std::string 方法1&#xff1a;使用toStdString()&#xff08;推荐&#xff09; QString qstr "你好&#xff0c;Qt世界"; std::string str qstr.toStdS…

机器学习+EEG熵进行双相情感障碍诊断的综合评估

摘要 双相情感障碍(BD)是一种常见的精神疾病&#xff0c;特点是躁狂或轻躁狂与抑郁交替发作&#xff0c;其严重程度各异&#xff0c;导致准确及时的诊断具有一定的挑战性。EEG的非线性特征被认为是精神障碍的生物标志物&#xff0c;能够反映大脑的非线性动态。尽管已有研究证明…

企业应用集成全析:架构、实践与展望

企业应用集成全析&#xff1a;架构、实践与展望 一、企业应用集成的基本概念1.1 定义1.2 目标 二、企业应用集成的层次架构2.1 数据集成2.2 应用系统集成2.3 业务流程集成​ 三、企业应用集成的关键技术3.1 中间件技术3.2 Web 服务技术​3.3 企业服务总线&#xff08;ESB&#…

【STL】list介绍(附与vector的比较)

文章目录 1.关于list2.使用2.1 list的构造2.2 list 迭代器的使用2.3 list 容量操作2.3.1 size()2.3.2 empty()2.3.3 resize() 2.4 list 元素访问2.4.1 front()2.4.2 back() 2.5 list 修改操作2.5.1 push_front()2.5.2 pop_front()2.5.3 push_back()2.5.4 pop_back()2.5.5 inser…

【Django】教程-12-柱状图

【Django】教程-1-安装创建项目目录结构介绍 【Django】教程-2-前端-目录结构介绍 【Django】教程-3-数据库相关介绍 【Django】教程-4-一个增删改查的Demo 【Django】教程-5-ModelForm增删改查规则校验【正则钩子函数】 【Django】教程-6-搜索框-条件查询前后端 【Django】教程…

SQL:DDL(数据定义语言)和DML(数据操作语言)

目录 什么是SQL&#xff1f; 1. DDL&#xff08;Data Definition Language&#xff0c;数据定义语言&#xff09; 2. DML&#xff08;Data Manipulation Language&#xff0c;数据操作语言&#xff09; DDL和DML的区别 什么是SQL&#xff1f; SQL&#xff08;Structured …

Chrome 135 版本开发者工具(DevTools)更新内容

Chrome 135 版本开发者工具&#xff08;DevTools&#xff09;更新内容 一、性能&#xff08;Performance&#xff09;面板改进 1. 性能面板中的配置文件和函数调用现已显示来源和脚本链接 Performance > Summary&#xff08;性能 > 概览&#xff09;选项卡现在会显示配…

[ctfshow web入门] web23

前置知识 include&#xff1a;包含一个文件&#xff0c;也可以包含一些其他东西&#xff0c;后续用到再解析 substr&#xff1a;对字符串进行切片&#xff0c;第一个参数是字符串&#xff0c;第二第三个参数出从第a个索引开始切n个&#xff0c;索引从0开始计数。 例如&#xf…

vue3 开发电子地图功能

文章目录 一、项目背景二、页面效果三、代码1.ElectronicMap.vue2.TransferDeskRSSIMap.vue3.Map.js4.src/stores/index.js Vuex存储属性 四、注意点本人其他相关文章链接 一、项目背景 项目采用&#xff1a;vue3javaArco DesignSpringBootOpenStreetMap 数据的地图切片服务。…

oracle 存储体系结构

oracle 存储体系结构 参考&#xff1a; Logical Storage Structures (oracle.com)

python-leetcode 66.寻找旋转排序数组中的最小值

题目&#xff1a; 已知一个长度为n的数组&#xff0c;预先按照升序排列&#xff0c;经由1到n次旋转后&#xff0c;得到输入数组&#xff0c;例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2]若…