c++哈希表——超实用的数据结构

文章目录

  • 1. 概念引入
    • 1.1 整数哈希
      • 1.1.1 直接取余法。
      • 1.1.2 哈希冲突
        • 1.1.2.1 开放寻址法
        • 1.1.2.2 拉链法
    • 1.2 字符串哈希
  • 3.结语

1. 概念引入

  • 哈希表是一种高效的数据结构 。
  • H a s h Hash Hash表又称为散列表,一般由 H a s h Hash Hash函数(散列函数)与链表结构共同实现。
  • 散列(映射)方法是使用函数 h h h 将元素 U U U映射到表 T [ 0... m − 1 ] T[0...m-1] T[0...m1] 的下标上 ( m = O ( ∣ U ∣ ) ) (m=O(|U|)) (m=O(U))。这样以 U U U中关键字为自变量,以h为函数的运算结果。
    就是相应结点的存储地址。从而达到在 O ( 1 ) O(1) O(1)时间内就可完成查找。

1.1 整数哈希

我们以一道例题来举例:哈希表。

这道题目是这么做的:

1.1.1 直接取余法。

关键字 k k k除以 m m m,取余数作为在 H a s h Hash Hash表中的位置。
函数表达式可以写成:
哈希函数 h ( k ) = k h(k) = k h(k)=k m o d mod mod m m m
一般 m m m 选择为素数,建议选择 2 e 5 + 10 2e5+10 2e5+10

1.1.2 哈希冲突

  • H a s h Hash Hash函数把复杂信息映射到一个容易维护的值域内。
  • 值域变小,有可能造成两个不同的信息被 H a s h Hash Hash函数映射为相同的值(两数同余), H a s h Hash Hash冲突,需要处理这种情况。
1.1.2.1 开放寻址法
  • 使用 H a s h Hash Hash函数 h h h把整数 x x x映射为 h [ x ] h[x] h[x],如果 h [ x ] h[x] h[x]已经有值,说明当前查询到的地址发生了冲突
  • 如果当前地址发生冲突,就向这个地址的右边继续查询,直到遇到 N U L L NULL NULL或值 x x x为止。

代码:

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int, int>
#define For(i, a, b) for(int i = a;i <= b;i++)
const int N = 2e5 + 3;
const int null = 0x3f3f3f3f;
int n, h[N];
int get(int x){int idx = (x % N + N) % N;while (h[idx] != null && h[idx] != x){idx = (idx == N ? 0 : idx + 1);}return idx;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);memset(h, 0x3f, sizeof h);int n, x;string op;cin >> n;while (n--){cin >> op;cin >> x;if (op[0] == 'I'){h[get(x)] = x;}else{cout << (h[get(x)] == x ? "Yes\n" : "No\n");}}return 0;
}

在这里插入图片描述

1.1.2.2 拉链法
  • Hash函数设为 h ( x ) = x h(x) = x % P h(x)=x ,这里 P P P 是较大质数,但不超过数组大小 N N N
  • 这个 H a s h Hash Hash函数 h h h 把整数分为了 P P P 类( M o d P = 1 , 2 , . . . , P − 1 Mod P = 1, 2, ..., P-1 ModP=1,2,...,P1),每一类用一个单独的链表存储。
  • 查找整数 x x x 的时候,就在整数 x x x 所在类的链表里进行查找。

代码:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define PII pair<int, int>
#define For(i, a, b) for(int i = a;i <= b;i++)
const int N = 2e5 + 3;
int head[N], val[N], nxt[N], idx;
void add(int x){int k = (x % N + N) % N;val[idx] = x;nxt[idx] = head[k];head[k] = idx++;
}
bool get(int x){int k = (x % N + N) % N;int res = head[k];while (res != -1){if (val[res] == x){return 1;}res = nxt[res];}return 0;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);memset(head, -1, sizeof head);int n;cin >> n;while (n--){char op;cin >> op;int x;cin >> x;if (op == 'I'){add(x);}else{if (get(x)){cout << "Yes\n";}else{cout << "No\n";}}}return 0;
}

在这里插入图片描述

1.2 字符串哈希

字符串 H a s h Hash Hash(字符串前缀 H a s h Hash Hash法),把字符串 s s s 变成一个 p p p 进制数字( H a s h Hash Hash值),实现不同的字符串映射到不同的数字。
字符串 s s s 中 的每个字符本质上就是一个数字( A S C I I ASCII ASCII值)。
s = s 0 s 1 s 2 s 3 ⋅ ⋅ ⋅ s n − 1 s = s_0 s_1s_2s_3···s_n - 1 s=s0s1s2s3⋅⋅⋅sn1
h ( s ) = s 0 ⋅ p n − 1 + s 1 ⋅ p n − 2 + ⋅ ⋅ ⋅ + s n − 1 ⋅ p 0 h(s) = s_0·p^{n-1}+s_1·p^{n-2}+···+s_n-1·p^0 h(s)=s0pn1+s1pn2+⋅⋅⋅+sn1p0

代码:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int unsigned long long
#define PII pair<int, int>
#define For(i, a, b) for(int i = a;i <= b;i++)const int N = 1e5 + 10;
int n, m;
char s[N];
int h[N], p[N];int get(int l, int r){return h[r] - h[l - 1] * p[r - l + 1];
}signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);cin >> n >> m >> s + 1;h[0] = 0;p[0] = 1;For (i, 1, n){h[i] = h[i - 1] * 131 + s[i];p[i] = p[i - 1] * 131;}while (m--){int l1, r1, l2, r2;cin >> l1 >> r1 >> l2 >> r2;if ((get(l1, r1)) == get(l2, r2)) {cout << "Yes\n";}else{cout << "No\n";}}return 0;
}

在这里插入图片描述

3.结语

今天的文章就到这里啦,三连必回哦!

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

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

相关文章

CentOS7 系统安装

系统下载 官方下载 清华源下载 安装流程 1. 选择安装系统 2. 选择安装语言 3. 设置网络链接 4. 设置静态IP ![img](https://img-blog.csdnimg.cn/img_convert/53bfedd54b838f95bd8bcb2efa232e23.png)设置时区 5. 磁盘设置&#xff0c;无特殊需求默认就好 6. 安装模式选择 7…

2023年年终总结 —— 致满载荣誉或满脸惆怅的你

开篇请允许我引用歌曲《西楼儿女》的一句歌词&#xff1a; 陌生的朋友你请听我讲&#xff0c;许多年前我也曾有梦想&#xff0c;想过满载荣誉回到家乡&#xff0c;这肆意的风压弯了海棠。 2023年即将过去&#xff0c;不管你这一年经历了多少&#xff0c;或是职场的得心应手、情…

从寄存器到内存访问(程序重定位角度)逐步认识8086处理器

文章目录 一、8086的通用寄存器二、8086的内存访问和字节序三、程序的分段3.1 常见名词含义3.2 指令执行过程 四、程序的重定位难题五、段地址和偏移地址六、8086内存访问困境七、8086选择段地址的策略八、8086的内存访问过程九、逻辑地址和分段的灵活性 一、8086的通用寄存器 …

基于AT24C02的多机通信

//单片机U3对AT24C02的读取程序 #include <reg51.h> // 包含51单片机寄存器定义的头文件 #include <intrins.h> //包含_nop_()函数定义的头文件 #define OP_READ 0xa1 // 器件1地址以及读取操作,0xa1即为1010 0001B #define OP_WRI…

18 UVM Scoreboard

UVM scoreboard是一个检查DUT功能的组件。它用analysis export从monitor接受transaction事务以进行检查。 uvm_scoreboard class declaration: virtual class uvm_scoreboard extends uvm_component User-defined scoreboard class declaration: 用户定义的scoreboard是从 u…

在thingsboard中跨设备动态时间段求遥测平均值

有a,b两个传感器,a传感器是电流,b传感器是振动频率。 当a传感器的电流大于x时,表明设备开始工作。 当a传感器的电流小于x时,表明设备停止工作。 要求,在规则链里求出设备工作时间段的振动频率的平均值,并基于平均值来判断是否发送告警。 这是一个典型的 在thingsboard中…

VSCODE 修改Test模式下的的java jvm堆内存大小

在settings.json中添加如下语句 "java.test.config": {"vmArgs": ["-Xmx12G"]},

Ps:八大混合模式及其在色彩渲染上的运用

在所有的图层混合模式中&#xff0c;有八种比较特别。 特别之处在于&#xff0c;其它的混合模式在修改图层的“不透明度”或“填充”时&#xff0c;效果是一样的。 而这八种混合模式使用“填充”比使用“不透明度”可带来更好的效果&#xff0c;有时甚至可以说是惊艳。 提示&am…

【前端面经】即时设计

目录 前言一面git 常见命令跨窗口通信vue 响应式原理发布订阅模式翻转二叉树Promise.all()扁平化数组面试官建议 二面Event Loop 原理Promise 相关css 描边方式requestAnimationReact 18 新特性JSX 相关react 输出两次函数式编程React 批处理机制http请求头有哪些本地存储性能优…

oracle-存储结构

文件包括 控制文件.ctl、数据文件.dbf、日志文件.log这三类放在存储上。 参数文件&#xff1a;空间的划分&#xff0c;进程的选用&#xff08;.ora&#xff09; oracle启动的时候需要读一下&#xff0c;数据库启动后&#xff0c;参数文件并不关闭&#xff0c;但即使文件丢了&a…

基于Python的电商手机数据可视化分析和推荐系统

1. 项目简介 本项目旨在通过Python技术栈对京东平台上的手机数据进行抓取、分析并构建一个简单的手机推荐系统。主要功能包括&#xff1a; 网络爬虫&#xff1a;从京东获取手机数据&#xff1b;数据分析&#xff1a;统计各厂商手机销售分布、市场占有率、价格区间和好评率&am…

RSA加密解密——用shell加密java解密

功能描述 使用shell opensll对明文进行RSA加密&#xff0c;将密文用java的RSA工具对密文解密。这应该是全网第一个同时用到shell和java的RSA加密解密教程。中间有很多坑&#xff0c;都踩过了&#xff0c;可以放心使用代码。 正确的实现流程 shell端 首先生成公钥私钥 &…