【数据结构 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 来说,代价是巨大的。该游戏的成功让首席执行官沟部拓郎最近在推特上表示,他可能因服务器运营费用而面临破产。据他透…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...
