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.mfbz.cn/a/281110.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【代码随想录】刷题笔记Day42

前言 这两天机器狗终于搞定了&#xff0c;一个控制ROS大佬&#xff0c;一个计院编程大佬&#xff0c;竟然真把创新点这个弄出来了&#xff0c;牛牛牛牛&#xff08;菜鸡我只能负责在旁边喊加油&#xff09;。下午翘了自辩课来刷题&#xff0c;这次应该是元旦前最后一刷了&…

车载电子电器架构 —— 电子电气系统开发角色定义

车载电子电器架构 —— 电子电气系统开发角色定义 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 注:本文12000字,深度思考者进!!! 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的…

鸿蒙应用开发 新闻数据加载

1 HTTP 数据请求概述 日常生活中我们使用应用程序看新闻、发送消息等&#xff0c;都需要连接到互联网&#xff0c;从服务端获取数据。例如&#xff0c;新闻应用可以从新闻服务器中获取最新的热点新闻&#xff0c;从而给用户打造更加丰富、更加实用的体验。 那么要实现这样一种…

技术阅读周刊第十二期

年前最后一篇推送&#xff0c;提前祝大家新年快乐。 技术阅读周刊&#xff0c;每周更新。 历史更新 20231201&#xff1a;第八期20231215&#xff1a;第十期20231122&#xff1a;第十一期 Deno vs Go: Native hello world performance | Tech Tonic URL: https://medium.com/de…

R306指纹识别模块的硬件接口

1.外部接口尺寸图 采集芯片外形尺寸&#xff1a;33.4*20.4*3.79 mm 2.串行通讯 R306 指纹模块通讯接口定义&#xff1a; 3.USB 通讯 4.接口说明 4.1 UART a) UART 缺省波特率为 57.6kbps&#xff0c;数据格式&#xff1a;8 位数据位&#xff08;低位在前&#xff09;&#…

【leetcode100-020】【矩阵】旋转图像

【题干】 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 【思路】 怎么还整上小学奥数题了&#xff08;不是对角翻转水平/垂…

什么是SEO?

什么是SEO&#xff1f; SEO代表“搜索引擎优化”。这是通过非付费&#xff08;也称为“自然”&#xff09;搜索引擎结果来提高网站流量的质量和数量以及品牌曝光率的做法。 尽管有首字母缩略词&#xff0c;但 SEO 既关乎搜索引擎本身&#xff0c;也关乎人。这是关于了解人们在…

设计模式(4)--类行为(10)--模板方法

1. 意图 定义一个操作中的算法的骨架&#xff0c;而将一些步骤延迟到子类中。 模板方法使子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 2. 两种角色 抽象类(Abstract Class)、具体类(Concrete Class) 3. 优点 3.1 一种代码复用的基本技术。提取公共行为&am…

现代建筑 Modern Design 展示前端界面html推荐

前言 一款展示现代建筑的网页 一、需求分析 一个现代建筑展示网站是指利用现代技术和设计风格&#xff0c;以展示和推广各种建筑项目和设计作品为主要目的的网站。 作为一个现代建筑展示网站&#xff0c;以下是一些需要的要素&#xff1a; 响应式设计&#xff1a;现代建筑展…

mixins混淆请求字典封装库

摘要&#xff1a; 页面请求要使用到很多重点的查询&#xff0c;写在本页面的逻辑代码太混乱&#xff0c;所以可以抽离封装成功一个js库混淆进来&#xff01; commonMixins.js: import {Toast} from "vant"; export const oplistMix {mounted() {this.GETSTORE_LOCA…

基于电商场景的高并发RocketMQ实战-Consumer端队列负载均衡分配机制、并发消费以及消费进度提交

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 【11来了】文章导读地址&#xff1a;点击查看文章导读&#xff01; &#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f3…

迅软科技助力高科技防泄密:从华为事件中汲取经验教训

近期&#xff0c;涉及华为芯片技术被窃一事引起广泛关注。据报道&#xff0c;华为海思的两个高管张某、刘某离职后成立尊湃通讯&#xff0c;然后以支付高薪、股权支付等方式&#xff0c;诱导多名海思研发人员跳槽其公司&#xff0c;并指使这些人员在离职前通过摘抄、截屏等方式…

MFC - 给系统菜单(About Dialog)发消息

文章目录 MFC - 给系统菜单(About Dialog)发消息概述笔记resource.h菜单的建立菜单项的处理MSDN上关于系统菜单项值的说法END MFC - 给系统菜单(About Dialog)发消息 概述 做了一个对话框程序, 在系统菜单(在程序上面的标题栏右击)中有"关于"的菜单. 这个是程序框架…

4.24 构建onnx结构模型-Slice

前言 构建onnx方式通常有两种&#xff1a; 1、通过代码转换成onnx结构&#xff0c;比如pytorch —> onnx 2、通过onnx 自定义结点&#xff0c;图&#xff0c;生成onnx结构 本文主要是简单学习和使用两种不同onnx结构&#xff0c; 下面以 Slice 结点进行分析 方式 方法一…

Grafana增加仪表盘

1.Grafana介绍 grafana 是一款采用Go语言编写的开源应用&#xff0c;主要用于大规模指标数据的可视化展现&#xff0c;是网络架构和应用分析中最流行的时序数据展示工具&#xff0c;目前已经支持绝大部分常用的时序数据库。 Grafana下载地址&#xff1a;https://grafana.com/g…

网际协议IPv4

基本介绍 网际协议IP是TCP/IP体系中两个重要的协议之一。IPv4虽有最终被IPv6取代的趋势&#xff0c;但它仍是当前使用的最重要的因特网协议。 与IP配套使用的还有3个协议&#xff1a; 地址解析协议ARP(Address Resolution Protocol)因特网控制报文协议ICMP(Internet Control …

年终跑步总结

第一个365天无间断年 以前也跑步很频繁&#xff0c;但今年是第一次365天未缺勤。年跑步量也是历来个人最多&#xff1a;2900km以上。 连续跑步天数累积超700天了 这里出现的签到天数累加只有666次&#xff0c;因为中间有跑步、但没有到app上签到&#xff0c;实际最近一次停…

EOS链Ubuntu环境Install Prebuilt Binaries(安装预构建的二进制文件)的安装

[TOC](EOS链Ubuntu环境Install Prebuilt Binaries(安装预构建的二进制文件)的安装) EOS官网&#xff1a;https://eos.io/ 第一步 Ubuntu安装命令&#xff1a; 以下有两种安装方式&#xff0c;可以任选其一&#xff1a; 本文章已经上传绑定资源&#xff0c;也可以用命令安装。…

【Matlab】ELM极限学习机时序预测算法

资源下载&#xff1a; https://download.csdn.net/download/vvoennvv/88681649 一&#xff0c;概述 ELM&#xff08;Extreme Learning Machine&#xff09;是一种单层前馈神经网络结构&#xff0c;与传统神经网络不同的是&#xff0c;ELM的隐层神经元权重以及偏置都是随机产生的…

微信小程序开发系列-09自定义组件样式特性

微信小程序开发系列目录 《微信小程序开发系列-01创建一个最小的小程序项目》《微信小程序开发系列-02注册小程序》《微信小程序开发系列-03全局配置中的“window”和“tabBar”》《微信小程序开发系列-04获取用户图像和昵称》《微信小程序开发系列-05登录小程序》《微信小程序…
最新文章