C++之开散列哈希表

ops/2025/1/12 11:46:02/

目录

闭散列哈希表

 元素的插入

元素的查找

 元素的删除


上期我们学习了闭散列哈希表,闭散列哈希表和开散列哈希表的区别就是插入的元素在冲突时,应对冲突的处理方式不同,本期我们将详细的学习闭散列哈希表。

闭散列哈希表

 闭散列哈希表图示如下。

开散列哈希表就是将冲突的元素通过一个单向链表链接起来。在闭散列哈希表中,当平衡因子的大小大于为0.7时,就需要进行扩容,这样可以尽可能避冲突。在开散列哈希表中,因为冲突的元素可以通过一张链表链接在同一位置,对于冲突的容忍性会比闭散列的容忍性较高,但是为了避免一个位置冲突的元素过多,所以在平衡因子为1时也需要进行扩容。

 元素的插入

bool insert(const pair<K, V>& pair){HashFunc<K> hf;Node* node = find(pair.first);if (node){return false;}if (_table.size() == 0 || _num * 10 / _table.size() > 10){int NewSize = _table.size() == 0 ? 10 : _table.size() * 2;vector<Node*> newtable;newtable.resize(NewSize);for (int i = 0; i < _table.size(); i++){Node* cur = _table[i];while(cur){Node* next = cur->_next;int num = hf(cur->_kv.first) % newtable.size();cur->_next = newtable[num];newtable[num] = cur;cur = next;}_table[i] = nullptr;}newtable.swap(_table);}int index = hf(pair.first) % _table.size();Node* newnode = new Node(pair);//头插newnode->_next = _table[index];_table[index] = newnode;_num++;return true;}

元素的插入同闭散列哈希表一样,也需要扩容,但是在进行扩容时,因为节点的创建是非常消耗空间的,所以我们不像闭散列哈希表一样,创建了一个哈希表对象去复用insert函数,而知识创建了一个vector对象,然后通过更改映射与指针的关系,实现扩容之后,新表中元素的映射。

元素的查找

Node* find(const K& key){if (_table.size() == 0){return nullptr;}HashFunc<K> hf;int index = hf(key) % _table.size();Node* cur = _table[index];while (cur){if (cur->_kv.first == key){return cur;}cur = cur->_next;}return nullptr;}

元素的查找原理很简单,因为我们是把所有冲突的元素放在了一张链表里,所以只需在特定映射位置的链表里找对应的元素即可。 

 元素的删除

bool erase(const K& key){if (_table.size() == 0){return false;}HashFunc<K> hf;int index = hf(key)% _table.size();Node* prev = nullptr;Node* cur = _table[index];while(cur){if (cur->_kv.first==key  ){if (prev == nullptr){//头删_table[index] = cur->_next;}else{//中间删除prev->_next = cur->_next;}--_num;delete cur;return true;}else{prev = cur;cur = cur->_next;}}return false;}

元素的删除,分为头删和中间删除,我们通过判断prev指针是否为空来判断是否是头删还是尾删,因为元素都是通过链表节点链接起来的,所以删除只需要更改指针的指向即可。 

测试代码

void opentest(){HashTable<int, int> ht;ht.insert(make_pair(1, 1));ht.insert(make_pair(2, 1));ht.insert(make_pair(3, 1));ht.insert(make_pair(4, 1));ht.insert(make_pair(5, 1));ht.insert(make_pair(6, 1));ht.insert(make_pair(7, 1));ht.insert(make_pair(8, 1));ht.insert(make_pair(9, 1));ht.insert(make_pair(10, 1));ht.insert(make_pair(11, 1));ht.insert(make_pair(12, 1));ht.erase(1);ht.erase(2);ht.erase(3);cout << ht.find(1) << endl;cout << ht.find(5) << endl;}}

调试代码,结果符合预期。 

以上便是开散列哈希表的所有内容。

本期内容到此结束^_^ 


http://www.ppmy.cn/ops/149436.html

相关文章

C#语言的数据结构

C#语言的数据结构探讨 数据结构是计算机科学中一种用于组织、存储和管理数据的方式。有效地使用数据结构能使算法更加高效&#xff0c;并提高程序的性能。在C#语言中&#xff0c;我们可以构建和使用多种数据结构&#xff0c;以满足不同的需求。本文将介绍C#中的常用数据结构&a…

SpringBoot操作spark处理hdfs文件

SpringBoot操作spark处理hdfs文件 1、导入依赖 <!-- spark依赖--><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.12</artifactId><version>3.2.2</version></dependency><depend…

STM32 : GPIO_TypeDef

结构体定义 (GPIO_TypeDef) 是STM32微控制器中用于描述GPIO端口寄存器的典型方式。每个GPIO端口&#xff08;如 GPIOA、GPIOB 等&#xff09;都由一组寄存器组成&#xff0c;这些寄存器控制和监控GPIO引脚的状态。 寄存器解释 CRL (Control Register Low): 低8位引脚的控制寄存…

数据库 -- 视图

1. 视图 1.1 什么是视图 视图是⼀个虚拟的表&#xff0c;它是基于⼀个或多个基本表或其他视图的查询结果集。视图本⾝不存储数据&#xff0c;⽽是通过执⾏查询来动态⽣成数据。⽤⼾可以像操作普通表⼀样使⽤视图进⾏查询、更新和管理。视图本⾝并不占⽤物理存储空间&#xff…

单片机实物成品-011 火灾监测

火灾监测&#xff08;20个版本&#xff09; 版本20&#xff1a; oled显示温湿度烟雾浓度火焰传感器天然气浓度窗户风扇水泵排气系统声光报警语音播报按键WIFI模块 ----------------------------------------------------------------------------- https://www.bilibili.com…

基于Python的音乐播放器 毕业设计-附源码73733

摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器&#xff0c;用户可以轻松管理自己的音乐库&#xff0c;播放喜爱的音乐&#xff0c;并享受音乐带来的愉悦体验。 首先&#xff0c;我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…

Java 工厂模式、工厂方法模式、抽象工厂模式

Java 工厂模式、工厂方法模式、抽象工厂模式 引言 在软件开发中&#xff0c;设计模式是解决特定问题的通用解决方案。工厂模式作为一种创建型设计模式&#xff0c;在对象创建过程中扮演着重要角色。本文将详细介绍Java中的工厂模式&#xff0c;包括其概念、应用场景、实现方式…

Streamlit+Selenium快速构建一个网络爬虫应用

项目需要从网上爬取数据&#xff0c;用了八爪鱼来进行测试&#xff0c;可以通过自定义任务&#xff0c;不需要编程即可实现对于数据的爬取&#xff0c;但是缺点是免费版本自定义任务有数量限制&#xff0c;另外在采集过程的控制上还不够便利&#xff0c;对于熟悉Python编程的人…