【数据结构 09】哈希
哈希算法:哈希也叫散列、映射,将任意长度的输入通过散列运算转化为固定长度的输出,该输出就是哈希值(散列值)。
哈希映射是一种压缩映射,通常情况下,散列值的空间远小于输入值的空间。
哈希运算的结果称为哈希值,哈希运算是不可逆过程,即不能通过哈希值推算出原值。
哈希运算常用于加密、位图、布隆过滤,位图的作用是海量数据的标记,布隆过滤器的作用是提高海量数据查询的效率(客户端向服务端查询数据)。
一、哈希函数
HashFunc.h
#pragma once
#include <iostream>// 仿函数
template<class K>
struct HashFunc
{size_t operator()(const K& key){return (size_t)key;}
};// 特化
template<>
struct HashFunc<std::string>
{size_t operator()(const std::string& str){size_t res = 0;for (const auto& ch : str){res *= 131; // 随机数取值,避免哈希冲突res += ch;}return res;}
};
哈希表:将数据根据哈希运算得到哈希值(关键值),再根据哈希值将数据映射在表中,哈希表通常情况是一个vector容器。哈希表分为闭散列和开散列(哈希桶)。
哈希表的数据增删与红黑树差别不大,各有优劣,但是哈希表的数据查询效率远高于红黑树。
二、闭散列

#define _CRT_SECURE_NO_WARNINGS 1#pragma
#include <iostream>
#include <vector>
#include "HashFunc.h"enum status
{EMPTY,EXIST,DELETE
};template<class K, class V>
struct CloseHashNode
{std::pair<K, V> _kv;status _status = EMPTY;
};template<class K, class V, class Hash = HashFunc<K>>
class CloseHash
{typedef CloseHashNode<K, V> Data;
public:CloseHash(): _n(0){_table.resize(10);}bool Insert(const std::pair<K, V>& kv){if (Find(kv.first))return false;// 负载因子为0.7if (_n * 10 / _table.size() >= 7){std::vector<Data> newTable;newTable.resize(2 * _table.size());for (int i = 0; i < _table.size(); ++i){if (_table[i]._status == EXIST){size_t pos = Hash()(_table[i]._kv.first) % newTable.size();while (newTable[pos]._status != EMPTY){pos = (++pos) % newTable.size();}newTable[pos] = _table[i];}}_table.swap(newTable);}size_t pos = Hash()(kv.first) % _table.size();while (_table[pos]._status != EMPTY){pos = (++pos) % _table.size();}_table[pos]._kv = kv;_table[pos]._status = EXIST;++_n;return true;}Data* Find(const K& key){size_t pos = Hash()(key) % _table.size();int cnt = 0;while (_table[pos]._status != EMPTY && cnt != _table.size()){if (key == _table[pos]._kv.first && _table[pos]._status == EXIST)return &_table[pos];pos = (++pos) % _table.size();++cnt;}return nullptr;}bool Erase(const K& key){Data* ret = Find(key);if (ret){ret->_status = DELETE;--_n;return true;}else{return false;}}private:std::vector<Data> _table;size_t _n;
};
三、开散列
开散列也称哈希桶,哈希桶的vector节点存储的是数据节点,相同哈希值的节点以链表的形式存储在同一个vector位置上,当节点数与vector容量的比值为平衡因子值(1)时,哈希桶扩容,扩容时重新遍历原表,将原表的元素重新取哈希进行映射,为了提高效率,不拷贝节点,而是改变节点的指向。

#define _CRT_SECURE_NO_WARNINGS 1#pragma once
#include <iostream>
#include <vector>
#include "HashFunc.h"template<class K, class V>
struct OpenHashNode
{std::pair<K, V> kv;OpenHashNode<K, V>* next;OpenHashNode(const std::pair<K, V>& x): kv(x), next(nullptr){}
};template<class K, class V, class Hash = HashFunc<K>>
class OpenHash
{typedef OpenHashNode<K, V> Node;
public:OpenHash(): _n(0){_table.resize(10, nullptr);}bool Insert(const std::pair<K, V>& kv){if (Find(kv.first))return false;// 检查扩容,平衡因子为 1if (_n == _table.size()){std::vector<Node*> newTable;newTable.resize(2 * _table.size(), nullptr);for (int i = 0; i < _table.size(); ++i){Node* cur = _table[i];while (cur){Node* next = cur->next;size_t pos = Hash()(cur->kv.first) % newTable.size();cur->next = newTable[pos];newTable[pos] = cur;cur = next;}}_table.swap(newTable);}// 插入新节点Node* newNode = new Node(kv);size_t pos = Hash()(newNode->kv.first) % _table.size();newNode->next = _table[pos];_table[pos] = newNode;++_n;return true;}Node* Find(const K& key){size_t pos = Hash()(key) % _table.size();Node* cur = _table[pos];while (cur){if (cur->kv.first == key)return cur;cur = cur->next;}return nullptr;}bool Erase(const K& key){Node* ret = Find(key);if (ret){size_t pos = Hash()(key) % _table.size();Node* cur = _table[pos];if (cur == ret){cur = ret->next;delete ret;ret = nullptr;}else{while (cur->next != ret){cur = cur->next;}cur->next = ret->next;delete ret;ret = nullptr;}--_n;return true;}else{return false;}}private:std::vector<Node*> _table;int _n;
};
四、测试
#define _CRT_SECURE_NO_WARNINGS 1#include "CloseHash.h"
#include "OpenHash.h"
using namespace std;void TestCloseHash()
{cout << "CloseHash: " << endl << endl;CloseHash<int, int> hash;int arr[] = { 34, 36, 12, 54, 5, 22, 65, 32, 13, 4, 1, 52 };for (auto& e : arr){hash.Insert(make_pair(e, e));}cout << hash.Find(12) << endl;cout << hash.Find(22) << endl;cout << hash.Find(32) << endl;cout << hash.Find(42) << endl;cout << hash.Find(52) << endl;cout << endl;hash.Erase(32);cout << hash.Find(12) << endl;cout << hash.Find(22) << endl;cout << hash.Find(32) << endl;cout << hash.Find(42) << endl;cout << hash.Find(52) << endl;
}void TestOpenHash()
{cout << endl << endl << "OpenHash: " << endl << endl;OpenHash<int, int> hash;int arr[] = { 34, 36, 12, 54, 5, 22, 65, 32, 13, 4, 1, 52 };for (auto& e : arr){hash.Insert(make_pair(e, e));}cout << hash.Find(12) << endl;cout << hash.Find(22) << endl;cout << hash.Find(32) << endl;cout << hash.Find(42) << endl;cout << hash.Find(52) << endl;cout << endl;hash.Erase(32);cout << hash.Find(12) << endl;cout << hash.Find(22) << endl;cout << hash.Find(32) << endl;cout << hash.Find(42) << endl;cout << hash.Find(52) << endl;
}int main()
{TestCloseHash();TestOpenHash();return 0;
}
相关文章:
【数据结构 09】哈希
哈希算法:哈希也叫散列、映射,将任意长度的输入通过散列运算转化为固定长度的输出,该输出就是哈希值(散列值)。 哈希映射是一种压缩映射,通常情况下,散列值的空间远小于输入值的空间。 哈希运…...
理解和管理Linux文件权限
理解和管理Linux文件权限 文件权限的基本概念和表示方式 文件权限管理在Linux系统中是非常重要的,它决定了谁可以访问、读取、写入或执行文件。文件权限以及所有者、所属组等属性可以通过 ls -l 命令查看。 在 ls -l 命令的输出中,文件的权限通常表示…...
爬虫(二)
1.同步获取短视频 1.只要播放地址对Json数据解析,先把列表找出: 2.只想要所有的播放地址,通过列表表达式循环遍历这个列表拿到每个对象,再从一个个对象里面找到Video,再从Video里面找到播放地址(play_addr),再从播放地址找到播放…...
Flink实战四_TableAPISQL
接上文:Flink实战三_时间语义 1、Table API和SQL是什么? 接下来理解下Flink的整个客户端API体系,Flink为流式/批量处理应用程序提供了不同级别的抽象: 这四层API是一个依次向上支撑的关系。 Flink API 最底层的抽象就是有状态实…...
海外云手机开辟企业跨境电商新道路
近几年,海外云手机为跨境电商、海外媒体引流、游戏行业等互联网领域注入了蓬勃活力。对于国内跨境电商而言,在亚马逊及其他平台上,短视频引流和社交电商营销成为最为有效的流量来源。如何通过海外云手机的助力,在新兴社交平台为企…...
【51单片机系列】中断优先级介绍及使用
文章来源:《51单片机原理及应用(第3版)》5.4节。 51单片机采用了自然优先级和人工设置高、低优先级的策略。 当CPU处理低优先级中断,又发生更高级中断时,此时中断处理过程如下图所示。 一个正在执行的低优先级中断服…...
.net core 6 集成 elasticsearch 并 使用分词器
1、nuget包安装NEST、安装elasticsearch、kibana、ik分词器、拼音分词器 2、创建操作对象 //索引库 static string indexName "testparticper"; //es 操作对象 ElasticClient elasticClient new ElasticClient(new ConnectionSettings(new Uri("http://192.…...
Unity项目从built-in升级到URP(包含早期版本和2023版本)
unity不同版本的升级URP的方式不一样,但是大体流程是相似的 首先是加载URP包 Windows -> package manager,在unity registry中找到Universal RP 2023版本: 更早的版本: 创建URP资源和渲染器 有些版本在加载时会自动创建&#…...
2月4号作业
编写程序实现二叉树的创建,三种遍历自己销毁 #include <myhead.h>#define TRUE 1 #define FALSE 0 #define OVERFLOW -2 #define OK 1 #define ERROR 0#define INIT_SIZE 20 #define INCREMENT_SIZE 5typedef int Status; typedef int TElemType; //存储结构…...
瑞_23种设计模式_建造者模式
文章目录 1 建造者模式(Builder Pattern)1.1 介绍1.2 概述1.3 创作者模式的结构 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 模式拓展 ★★★4.1 重构前4.2 重构后 5 总结5.1 建造者模式优缺点5.2 建造者模式使用场景5.3 建造者模式 …...
GA/T 1707-2019 防爆安全门检测
防爆安全门是指能抵抗爆炸冲击波作用的特种防护门,根据防爆门的防爆性能的不同,分为非接触爆炸防爆门和防接触爆炸防爆门,根据防爆能力的不同,分为不同等级。 GA/T 1707-2019 防爆安全门检测项目 测试项目 测试标准 外观质量 …...
k8s学习-数据管理
在Docker中我们知道,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中,常用的手段就是Volume数据卷。在K8S中,也提供了存储模型Volume&…...
java hutool工具类实现将数据下载到excel
通过hutool工具类,对于excel的操作变得非常简单,上篇介绍的是excel的上传,对excel的操作,核心代码只有一行。本篇的excel的下载,核心数据也不超过两行,简洁方便,特别适合当下的低代码操作。 下载…...
【C/Python】Gtk部件ListStore的使用
一、C语言 在GTK中,Gtk.ListStore是一个实现了Gtk.TreeModel接口的存储模型,用于在如Gtk.TreeView这样的控件中存储数据。以下是一个简单的使用Gtk.ListStore的C语言示例,该示例创建了一个列表,并在图形界面中显示: …...
Swift 入门之自定义类型的模式匹配(Pattern Matching)
概览 小伙伴们都知道 Swift 是一门简洁、类型安全、极富表现力以及“性感迷人”的编程语言。 和大多数语言一样,在 Swift 中也有一些隐藏着的、不为人知的宝藏特性。利用它们我们可以极大增加撸码的愉悦和成就感。 其中,模式匹配(Pattern …...
MySQL-----DML基础操作
DML语句 DML英文全称是Data Manipulation Language(数据操作语言),用来对数据库中表的数据记录进行增删改操作。 ▶ 添加数据(INSERT) 【语法】 1. 给指定字段添加数据 INSERTO 表名 (字段名1,字段名2,...) VALUES (值1,值2,...); 2.给全…...
提前祝大家新年好!来看看社区 2023 都得了哪些奖吧
大噶好!转眼马上就是“龙”历新年啦,不知道大家这周的工作热情怎么样呢?小陈的心已经在殷切期盼回家过年了~ RTE 开发者社区预祝诸位: 2024 年 🐲龙年添财气,万事皆胜意! 回顾过去…...
Redis核心技术与实战【学习笔记】 - 19.Pika:基于SSD实现大容量“Redis”
前言 随着业务数据的增加(比如电商业务中,随着用户规模和商品数量的增加),就需要 Redis 能保存更多的数据。你可能会想到使用 Redis 切片集群,把数据分散保存到不同的实例上。但是这样做的话,如果要保存的…...
qt-C++笔记之contains()和isEmpty()函数、以及部分其他函数列举
qt-C笔记之contains()和isEmpty()函数、以及部分其他函数列举 code review! 文章目录 qt-C笔记之contains()和isEmpty()函数、以及部分其他函数列举contains()isEmpty() 类似的其他函数列举通用容器类函数字符串特有函数 在Qt C开发中, contains() 和 isEmpty()…...
极速搭建幻兽帕鲁私服,叫上好友春节假期一起联机畅玩帕鲁
文章目录 前言幻兽帕鲁私服详细部署教程查看服务器开始游戏自定义游戏参数配置 前言 行业资讯 《幻兽帕鲁》的火爆对开发商 Pocketpair 来说,代价是巨大的。该游戏的成功让首席执行官沟部拓郎最近在推特上表示,他可能因服务器运营费用而面临破产。据他透…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
