【基础算法】哈希表(拉链法)

news2024/11/29 2:46:21

🌹作者:云小逸
📝个人主页:云小逸的主页
📝Github:云小逸的Github
🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。==希望春天来之前,我们一起面朝大海,春暖花开!==🤟
👏专栏:C++👏 👏专栏:Java语言👏👏专栏:Linux学习👏
👏专栏:C语言初阶👏👏专栏:数据结构👏👏专栏:备战蓝桥杯👏

文章目录

  • 前言
  • 哈希表:
    • 哈希表的含义:
    • 哈希表的作用:
    • 哈希表的思想:
      • 1.映射
      • 2.冲突:
    • 例题:
      • 题目:
      • 输入格式
      • 输出格式
      • 数据范围
      • 输入样例:
      • 输出样例:
    • 拉链法:
      • 1.先将原数组值域映射到哈希函数:
      • 2.建立一个槽,将映射的结果链接到槽上
      • 3.取模的N要为质数,且尽可能地离2的整数次幂尽可能的远。
      • 代码:
      • 代码解析:
  • 最后


前言

今天我们来学习一下新知识【哈希表】,这个是算法中比较重要的知识点,希望下面我的讲解你可以喜欢。如果有错误,请私信告知,望见谅。
——————————————————————————————————————————

首先先写上几句话:献给坚持创作的我和点开这篇文章希望进步的你
1.很喜欢《稻盛和夫对年轻人的忠告》里这段话:“大部分人对吃苦的含义了解得太浅了。吃苦不是穷,而是一个人长时间为了某个目标而聚焦的能力。在这个过程中,放弃娱乐生活,放弃无效社交,放弃无意义的消费以及在此过程中不被理解的孤独。”它本质是一种自控力,自制力,坚持和深度思考的能力。

2.以前我被误解的时候,我总会想去解释,你误会我了,我不是这样的人,我会想尽一切办法去证明自己。而现在,对于别人的误解,我不在乎也不想去辩解,我信任的人误会我,我会觉得挺好的,原来我在你心里是这样的人。
鱼那么相信水,水却煮了鱼;叶子那么信任风,风却吹落了叶;在自己的世界里独善其身,取悦自己,在别人的世界里顺其自然。

3.看到过这样一段话:“我希望你努力,不是为了要跟别人比成绩,而是因为,我希望你将来拥有选择的权利,选择有意义的生活,而不是被迫谋生。
当我们努力之后,我们才有机会不拘泥于方寸之地,不用只过着毫无新意、一眼望到头、没任何期待的日子。拥有选择权,我们才有底气和实力去选择我们想要的生活。

哈希表:

哈希表的含义:

在这里插入图片描述
上面是百度百科的说法;

散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算出一个键值的函数,将所需查询的数据映射到表中一个位置来让人访问,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。

这是维基百科的解释,

一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表〈和建立人名z到首字母F(赏)的一个函数关系),在首字母为W的表中查找“王”姓的电话号码,显然比宜直接查找就要快得多。这里使用人名作为关键字,“取首字母”是这个例子中散列函数的函数法则F(),存放首字母的表对应荀列表。关键字和函数法则理论上可以任意确定.

两者在对于哈希表的解释都不约而同的说了两点:码值和映射

在这里插入图片描述
下面借助百度百科的这张图便于你的理解:
先建立一个哈希函数(设定一个范围),再将不同的数分别映射到哈希函数上。

哈希表的作用:

把一个复杂的数据结构(值域,数据)映射到[0,n];
n一般是10的五次方或者10的六次方
如将[0,109]映射到[0,105]

哈希表的思想:

1.映射

将一段较大的数组映射到一段相对较小的数组,当要查找一个元素的时候,可以根据这个元素所映射对应的位置进行直接查找,而不是遍历查找,这样就可以更加高效的完成查找功能。
注:哈希一般常用的是增加和查找功能,如果想要删除一个数据,也不是真正意义上的删除,而是设定一个布尔数值,布尔值为false时代表删除这个数据。

2.冲突:

我们可以从这个图上的得知:多个数据可能会映射到同一个数值的情况。
在这里插入图片描述
针对这个情况,处理冲突有多重方法,如:

1.拉链法:
2.开放寻址法
3.再散列法
4.建立一个公共溢出区

这里详细介绍一下:拉链法和开放寻址法

例题:

题目:

维护一个集合,支持如下几种操作:
I x,插入一个数 x;
Q x,询问数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果。

输入格式

第一行包含整数 N,表示操作数量。接下来 N 行,每行包含一个操作指令,操作指令为 I x,Q x 中的一种。

输出格式

对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No。
每个结果占一行。

数据范围

1≤N≤105
−109≤x≤109

输入样例:

5
I 1
I 2
I 3
Q 2
Q 5

输出样例:

Yes
No

拉链法:

1.先将原数组值域映射到哈希函数:

如果值域为[-109,109],将其映射到[0,105]
则 x mod105 (mod是取模)这样就可以使其范围在[0,105],
上面的数值都是假设便于你的理解。
真正的代码应该是这样的:

int k = (x % N + N) % N;

这个代码的意思是将x取余将x映射到[0,N]范围内。
因为在C++中如果负数取模后仍然是负数,因此需要先取模后加上N再对N取模其结果一定是一个正数。

2.建立一个槽,将映射的结果链接到槽上

在这里插入图片描述
如上图所示,假设11的映射为3,23的映射也是3,将11链接槽上的3,将23链接在11后面,这个使用的是链表的结构存储拉链。

3.取模的N要为质数,且尽可能地离2的整数次幂尽可能的远。

在这里插入图片描述
这样的取N冲突的概率是最小的。

代码:

#include <cstring>
#include <iostream>

using namespace std;

const int N = 100003;//这里可以自己写一个求大于100000第一个质数的代码求出即可

int h[N];//这是上面说的开一个槽
int e[N], ne[N], idx;//与槽链接的拉链,用链表存储,
                    //e[N]用来存值,ne[N]下一个的位置,idx表示当前移动到哪一个位置

void insert(int x)
{
    int k = (x % N + N) % N;//k是哈希值
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx ++ ;//插入操作,类似于头插
}

bool find(int x)
{
    int k = (x % N + N) % N;
    for (int i = h[k]; i != -1; i = ne[i])
        if (e[i] == x)
            return true;

    return false;
}

int main()
{
    int n;
    scanf("%d", &n);

    memset(h, -1, sizeof h);//将槽清空,空指针一般用-1来表示

    while (n -- )
    {
        char op[2];
        int x;
        scanf("%s%d", op, &x);

        if (*op == 'I') insert(x);
        else
        {
            if (find(x)) puts("Yes");
            else puts("No");
        }
    }

    return 0;
}

代码解析:

const int N = 100003;//这里可以自己写一个求大于100000第一个质数的代码求出即可

int h[N];//这是上面说的开一个槽
int e[N], ne[N], idx;//与槽链接的拉链,用链表存储,
                    //e[N]用来存值,ne[N]下一个的位置,idx表示当前移动到哪一个位置

在这里插入图片描述

这里存一个字符用的是字符数组,读入字符串,而不是直接的一个字符进行存储,因为将其以一个字符串进行读入,这样scanf可以自动忽略掉空格和回车,这样可以降低出错概率。

void insert(int x)
{
    int k = (x % N + N) % N;//k是哈希值
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx ++ ;//插入操作,类似于头插
}

这个是插入操作,类似于链表的头插。
下面做一个动图,便于你的理解:
在这里插入图片描述

最后

十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:

1.这些年来一直在提醒自己一件事,千万不要感动自己,大部分人看似努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几个小时,多久没放假了。如果这些东西也值得炫耀,那么富士康流水线上任何一个人都比你努力多了。
人难免天生有自怜情绪,唯有时刻保持清醒,才看得清真正的价值在哪里。

2.这一生中有许多的人朝我走来,然后又匆匆忙忙的消失在人山人海中,那些人与我短暂交错,尾声潮落。从开始的不舍到最后的习以为常,便明白这是人生常态。真心待人,开始不再执着任何一段关系,即使是阶段性的陪伴,在相处的过程中我们开心就好,就活在当下。

海阔凭鱼跃,天高任鸟飞,路要朝前走,人要往前看。山林不向四季起誓,枯荣随缘,海洋不需对沙岸许诺,遇合尽兴。

3.见了太多糟糕的事情,反倒觉得一切都会好起来。心情不好就听歌,饿了就找吃的,怕黑就开灯,喜欢的东西就赚钱买。
有人紧握你的手就可能会松开,有人给你承诺也会有失言的时候,长大后才发现真正想要的东西总归要自己争取,只有自己才不会辜负自己。
顺其自然真的是我对当下的生活态度了,人就应该活在当下,把今天过得很积极明天一定不会太差。别想太多,好好生活,也许日子过着过着就有答案了。

最后如果觉得我写的还不错,请不要忘记点赞✌,收藏✌,加关注✌哦(。・ω・。)

愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚菜鸟逐渐成为大佬。加油,为自己点赞!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++的OpenCV】第四课-OpenCV图像常用操作(一):Mat对象深化学习、灰度、ROI

我们开始图像处理的基本操作的了解一、图像对象本身的加深学习1.1 Mat对象和ROI1.1.1 创建一个明确的Mat对象1.1.2 感兴趣的区域ROI二、图像的灰度处理2.1 概念2.2 cvtColor()函数2.3 示例一、图像对象本身的加深学习 1.1 Mat对象和ROI 这是一个技术经验的浅尝&#xff0c;所以…

什么是 CSAT?这份客户满意度流程指南请查收

什么是 CSAT&#xff1f;如何计算我的客户满意度分数&#xff1f;大中型公司应该熟悉这些术语。以下文章旨在教您有关客户满意度流程的所有内容 - 基本的CSAT概念、创建CSAT调查的好处、如何创建CSAT调查。配图来源&#xff1a; SaleSmartly(ss客服) 一、什么是 CSAT&#xff1…

算法笔记(十二)—— Manacher算法(回文子串)

计算字符串内的最大回文子串&#xff0c;常用的暴力扩散在应对长度为偶数的回文时会遇到一些问题。 Manacher基础&#xff1a;对字符串进行填充&#xff0c;在字符串开头结尾以及字符间填充‘#’&#xff0c;以来应对偶数回文时的问题。&#xff08;这是采用暴力扩再除2&#x…

[黑马程序员SSM框架教程]03 spring核心概念

IOC/DI 书写现状&#xff1a;耦合度偏高 如图&#xff1a;传统书写代码左边业务层需要new一个对象进行业务实现。当数据层优化代码BookDaoImpl2就需要动业务层代码重新修改new的对象。导致代码耦合度偏高。 解决办法&#xff1a;使用对象&#xff0c;不要主动new对象&#xff…

kubernetes traefik ingress 安装部署以及使用和注意点

1、简介 Traefik 是一款 open-source 边缘路由器&#xff0c;可让您轻松地发布服务. 它接收来自您的系统请求&#xff0c;并找出负责处理它们的后端服务组件。 traefik 与众不同在于它能够自动发现适合您服务的配置。 当 Traefik 检查您的基础设施时&#xff0c;它会发现相关信…

Redisson实现分布式锁

目录Redisson简介Redisson实现分布式锁步骤引入依赖application.ymlRedisson 配置类Redisson分布式锁实现Redisson简介 Redis 是最流行的 NoSQL 数据库解决方案之一&#xff0c;而 Java 是世界上最流行&#xff08;注意&#xff0c;没有说“最好”&#xff09;的编程语言之一。…

Matthew Ball:十多年后AR/VR为何依然发展缓慢?

2010年&#xff0c;Magic Leap和微软就开始研发AR技术&#xff0c;直到2012年Oculus才成立&#xff0c;AR/VR经过了13年左右的时间&#xff0c;虽然受到越来越多人关注&#xff0c;但发展依然缓慢。VR的主要应用场景还是游戏&#xff0c;但VR游戏只是游戏市场的一个分支&#x…

第七章.深度学习

第七章.深度学习 7.1 深度学习 深度学习是加深了层的深度神经网络。 1.加深层的好处 1).可以减少网络的参数数量 5*5的卷积运算示例&#xff1a; 重复两次3*3的卷积层示例&#xff1a; 图像说明&#xff1a; ①.一次5 * 5的卷积运算的区域可以由两次3 * 3的卷积运算抵消&a…

服务端开发Java之备战秋招面试篇1

在这个面试造火箭工作拧螺丝的时代背景下&#xff0c;感觉不是很好&#xff0c;不过还好也是拿到了还行的offer&#xff0c;准备去实习了&#xff0c;接下来就是边实习边准备秋招了&#xff0c;这半年把&#xff08;技术栈八股文面经算法题项目&#xff09;吃透&#xff0c;希望…

打破数据孤岛,Apache Doris 助力纵腾集团快速构建流批一体数仓架构|最佳实践

福建纵腾网络有限公司&#xff08;简称“纵腾集团”&#xff09;成立于 2009 年&#xff0c; 以“全球跨境电商基础设施服务商”为企业定位&#xff0c;聚焦跨境仓储与物流&#xff0c; 为全球跨境电商商户、出口贸易企业、出海品牌商提供海外仓储、商业专线物流、定制化物流等…

【C++】vector 模拟实现

vectorvector 容器vector 基本使用vector 定义库中各类接口的使用迭代器容量相关接口元素访问相关接口元素修改相关接口模拟实现 vector前期准备构造与析构赋值运算符重载迭代器相关容量相关元素访问相关元素的修改相关二维数组的创建对于自定义类型数据的测试vector 容器 C S…

Python实战之小说下载神器(二)整本小说下载:看小说不用这个程序,我实在替你感到可惜*(小说爱好者必备)

前言 这次的是一个系列内容给大家讲解一下何一步一步实现一个完整的实战项目案例系列之小说下载神器&#xff08;二&#xff09;&#xff08;GUI界面化程序&#xff09; 单章小说下载保存数据——整本小说下载 你有看小说“中毒”的经历嘛&#xff1f;小编多多少少还是爱看小说…

基于react+nodejs+mysql开发用户中心,用于项管理加入的项目的用户认证

基于reactnodejsmysql开发用户中心&#xff0c;用于项管理加入的项目的用户认证用户中心功能介绍页面截图后端采用架构user表projects表project_user表仓库地址用户中心功能介绍 用户中心项目&#xff0c;用于统一管理用户信息、登录、注册、鉴权等 功能如下&#xff1a; 用…

[qiankun]实战问题汇总

[qiankun]实战问题汇总ERROR SyntaxError: Cannot use import statement outside a module问题分析解决方案子应用命名问题问题分析解决方案jsonpFunction详细错误信息问题分析解决方案微应用的注册问题Uncaught Error: application cli5-beta6-test-name died in status LOADI…

2月,真的不要跳槽。

新年已经过去&#xff0c;马上就到金三银四跳槽季了&#xff0c;一些不满现状&#xff0c;被外界的“高薪”“好福利”吸引的人&#xff0c;一般就在这时候毅然决然地跳槽了。 在此展示一套学习笔记 / 面试手册&#xff0c;年后跳槽的朋友可以好好刷一刷&#xff0c;还是挺有必…

Zebec官方辟谣“我们与Protradex没有任何关系”

近日&#xff0c;流支付协议Zebec Protocol在其官方推特上&#xff0c;发表了一个辟谣澄清声明。该条推特推文表示&#xff0c;“Zebec 与 Protradex 没有任何关系或产生关联。他们&#xff08; Protradex &#xff09;声称Zebec 生态正在支持他们&#xff0c;但这是错误的。随…

上海亚商投顾:沪指失守3300点 卫星导航概念全天强势

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。市场情绪指数早间低开后震荡回升&#xff0c;沪指盘中一度翻红&#xff0c;随后又再度走低&#xff0c;创业板指午后跌近1%。…

基于GIS计算降雨侵蚀力R因子

一、数据来源介绍 &#xff08;一&#xff09;行政边界数据 本文所用到的河北唐山行政边界数据来源于中国科学院资源环境科学与数据中心&#xff08;https://www.resdc.cn/Default.aspx&#xff09;。 &#xff08;二&#xff09;降水量数据 本文所用到的降水量数据来源于国家…

【Java基础 下】 025 -- 阶段项目(斗地主)

目录 斗地主 一、斗地主游戏1 -- 准洗发&#xff08;控制台版&#xff09; 1、准备牌 2、洗牌 3、发牌 4、看牌 二、斗地主游戏2 -- 给牌排序①&#xff08;利用序号进行排序&#xff09; 2、洗牌 3、发牌 4、看牌 三、斗地主游戏2 -- 给牌排序②&#xff08;给每一张牌计算价值…

118.Android 简单的分组列表(BaseRecyclerViewAdapterHelper)

//1.第一步 导入依赖库&#xff1a; //RecyclerView implementation com.android.support:recyclerview-v7:28.0.0 //RecyclerAdapter implementation com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28 //2.第二步 新建SectionActivity页面&#xff1a; //manifest…