哈希表基础

UG NX与PLC-1500的在环虚拟测试 TIA、PLCSIM、NetToPLCsim、KEPServerEX以及UG NX的在环虚拟测试 阅读详情

哈希表概述

哈希表(散列表),大家看到这两个名称知道都是指hash table就可以了)。
哈希表是底层是数组,哈希表中关键字key就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:
在这里插入图片描述
key对应的数组的下标,而下标对应的数组里的值就是value。

一般哈希表都是用来快速判断一个元素是否出现集合里。
例如要查询一个人是否在这个班里。要枚举的话时间复杂度O(n),但如果使用哈希表的话, 只需要O(1)就可以做到。我们只需要初始化把班级里学生的名字都存在哈希表里,在查询的时候通过索引(名字)直接就可以知道这位同学在不在这个班级里了。
将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数。

哈希函数

哈希函数如下图所示,通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。在这里插入图片描述
如果hashCode得到的数值大于哈希表的大小了,也就是大于tableSize了,怎么办呢?此时为了保证映射出来的索引数值都落在哈希表上,我们会再次对数值做一个取模的操作,就要我们就保证了学生姓名一定可以映射到哈希表上了。此时问题又来了,哈希表我们刚刚说过,就是一个数组。一旦开辟,大小就固定了,如果学生的数量大于哈希表的大小怎么办,此时就算哈希函数计算的再均匀,也避免不了会有几位学生的名字同时映射到哈希表 同一个索引下标的位置。

哈希碰撞

如图所示,小李和小王都映射到了索引下标 1 的位置,这一现象叫做哈希碰撞。
在这里插入图片描述
一般哈希碰撞有两种解决方法, 拉链法和线性探测法。

拉链法

刚刚小李和小王在索引1的位置发生了冲突,发生冲突的元素都被存储在链表中。 这样我们就可以通过索引找到小李和小王了
在这里插入图片描述

(数据规模是dataSize, 哈希表的大小为tableSize)

其实拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。

线性探测法

使用线性探测法,一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题。
例如冲突的位置,放了小李,那么就向下找一个空位放置小王的信息。所以要求tableSize一定要大于dataSize ,要不然哈希表上就没有空置的位置来存放冲突的数据了。如图所示:在这里插入图片描述

常见的三种哈希结构

当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。
数组
set (集合)
map(映射)
这里数组就没啥可说的了,我们来看一下set。

在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示:!](https://img-blog.csdnimg.cn/af81775262304bea81af1ff58af30f14.png)

std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。在这里插入图片描述std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。

当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。

那么再来看一下map ,在map 是一个key ,value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的。

虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,但是std::set、std::multiset 依然使用哈希函数来做映射,只不过底层的符号表使用了红黑树来存储数据,所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法。 map也是一样的道理。

一些C++的经典书籍上 例如STL源码剖析,说到了hash_set hash_map,这个与unordered_set,unordered_map又有什么关系呢?实际上功能都是一样一样的, 但是unordered_set在C++11的时候被引入标准库了,而hash_set并没有,所以建议还是使用unordered_set比较好,这就好比一个是官方认证的,hash_set,hash_map 是C++11标准之前民间高手自发造的轮子。
在这里插入图片描述

典型OJ习题

力扣.有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例 1:

输入: s = “anagram”, t = “nagaram”
输出: true

示例 2:

输入 : s = “rat”, t = “car”
输出: false

思路

暴力的方法这里就不做介绍了,直接看一下有没有更优的方式。
数组其实就是一个简单哈希表,而且这道题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数。
需要定义一个多大的数组呢,定一个数组叫做hash_map,大小为26 就可以了,初始化为0,因为字符a到字符z的ASCII也是26个连续的数值。
再遍历 字符串s的时候,只需要将 s[i] - ‘a’ 所在的元素做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。 这样就将字符串s中字符出现的次数,统计出来了。那看一下如何检查字符串t中是否出现了这些字符,同样在遍历字符串t的时候,对t中出现的字符映射哈希表索引上的数值再做-1的操作。
那么最后检查一下,hash_map数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。
最后如果record数组所有元素都为零0,说明字符串s和t是字母异位词,return true。
时间复杂度为O(n),空间上因为定义是的一个常量大小的辅助数组,所以空间复杂度为O(1)。
C++ 代码如下:

class Solution {
public:
    bool isAnagram(string s, string t) {
        //需要把字符映射到数组也就是哈希表的索引下标上,因为字符a到字符z的ASCII是26个连续的数值
        //所以字符a映射为下标0,相应的字符z映射为下标25。
        int hash_map[26] = {0};
        for (auto ch : s){
            hash_map[ch - 'a']++;
        }

        for (auto ch : t){
            hash_map[ch - 'a']--;
        }
        
        for (auto e : hash_map){
            if(e!=0)
                return false;
        }
        return true;
    }
};

383. 赎金信

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
在这里插入图片描述
c++代码如下:

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        // 字符数不够明显就无法拼凑,直接返回
        if (magazine.length() < ransomNote.length())
            return false;
        vector<int> hash_map(26);
        // 构建hash数组
        for(auto ch : magazine)
            hash_map[ch - 'a']++;
        
        for (auto ch :ransomNote){
            hash_map[ch - 'a']--;

            // 短串中一旦遍历到长串中没有的字符,hash值就-1,直接返回false  
            if(hash_map[ch-'a']<0)
                return false;
        }
        return true; 
    }
};

总结

总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。如果在做题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!

io_uring vs epoll ,谁在网络编程领域更胜一筹? 简介:从定量分析的角度,通过量化 io_uring 和 epoll 两种编程框架下的相关操作的耗时,来分析二者的性能差异。 本文作者:王小光,「高性能存储技术SIG」核心成员。 背景 io_uring 在传统存储 io 场景已经证明其价值,但 io_uring 不仅支持传统存储 io,也支持网络 io。io_uring 社区有众多的开发者尝试将 io_uring 用于网络应用。我们之前也在《你认为 io_uring 只适用于存储 IO?大错特错!》中也探索过 io_uring 在网络场景的应用及其 阅读详情

相关推荐

CANoe: Panel的上位机控制方法

本文介绍了不同于IG的报文控制方法,实现了Panel面板的控制模式。

Jonsnow3zz的博客 1405

哈希表的简述

哈希表的建立与简述

m0_60492395的博客 866

ROS学习笔记之——无人机PID调参过程记录

For cooperaive inquiries, please visit the website:guanweipeng.com

gwpscut的博客 6827

哈希表及字符哈希

一、 定义 哈希表是又称散列表,一种以 “key-value” 形式存储数据的数据结构(h[key] = value)。输入查找的值 key,就可以快速地找到其对应的 value。 可以把哈希表理解为一种高级的数组,这种数组的下标可以是很大的整数,浮点数,字符串甚至结构体。 但如果key值很大超出下标范围,这时就体现了哈希的作用,也就是key值的使用。 二、key值的使用 当 key 的范围比较小的时候,可以直接把 key 作为数组的下标。 当 key 的范围比较大,比如以 10^9范围内的整数

j_x323u的博客 1089

STM32解码EM4100的曼彻斯特编码(库函数版本)

前言: 前些日子老师布置一个任务叫我们焊接一个RFID读卡器,其中刚好我们手上也有一个STM32F103RBT6开发板,老师于是布置任务叫我们用STM32完成对EM4100进行读卡操作 EM4100简介: 中 文 名:EM4100卡 存储容量:64bit 工作频率:125KHZ 读写距离:2-15cm 产品名称:EM4100/EM4102卡 芯片类型:μEM瑞士微电 EM4100/EM4102 擦写寿命:读不限,只读 外形尺寸:ISO标准卡/厚卡 封装材料:PVC、ABS 典型应用:身份识别、考勤系统、门禁

Gancenty 8597

Ubuntu20.04系统Cuckoo sandbox所需环境搭建及安装(超详细图文)

请勿叫我大神,我只是互联网的搬运工~ 前言 本教程以Ubuntu20桌面版作为示范,服务器版同样适用,但可能稍微麻烦一点,服务器版本的话安装Xmanage套装使用可能会相对轻松一些,由于后面会使用到vbox的使用,对vbox命令行操作不熟悉的小伙伴用xmanage可能会相对轻松一点。 提示:以下是本篇文章正文内容,下面案例可供参考 安装ubuntu20桌面版 步骤1:转到https://ubuntu.com/download/desktop下载下载.iso。 步骤2:使用您选择的虚拟机监控程序(VMWa

ElsonHY的博客 1万+

C语言实现哈希表(key为字符型)

简单实现了哈希表的插入和查找功能,简要说明如下: 1、数据结构: struct HashNode {             char* sKey;     //键             int nValue;      //值             HashNode* pNext; //当Hash值冲突时,指向HASH值相同的下一个节点。 }

oscarjulia的博客 3061

无人机通信安全渗透测试:从信号拦截到GPS欺骗的完整攻防框架

在物联网和智能设备普及的背景下,无线通信安全成为关键基础设施防护的核心环节。其原理在于,通过软件定义无线电等设备对空中的射频信号进行捕获、分析与模拟,从而评估通信协议在加密、认证和防重放等方面的脆弱性。这项技术的价值在于,它能主动发现并修复系统设计缺陷,避免因信号被拦截或欺骗导致设备被劫持、数据泄露等重大安全事件。其应用场景广泛,涵盖消费电子、工业控制及关键基础设施等领域。本文聚焦于无人机这一典型移动物联网终端,深入探讨如何构建一套针对其通信链路的渗透测试方法论,其中涉及信号拦截、协议逆向等关键技术,旨在为

weixin_34128237的博客 389

哈希表

一、什么是Hash表 哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 记录的存储位置=f(关键字) 这里的对应关系f称为散列函数,又称为哈希(Hash函数),采用散列技术将记录存储在一块连续的存储空间中,这...

心猿意碼 8370

智能车图像处理19-进阶篇11--斜入十字补线

这篇文章主要讲述智能车竞赛中如何对于斜入十字进行补线操作。

taiyuezyh的博客 7477

【乐企】开票控制服务

例子:企业信息初始化。

九七的博客 451

【C++哈希表】

c++哈希表基础操作学习 对于哈希表的每一个元素,我们需要通过箭头语法来访问元素内部,结构如下

weixin_61639290的博客 711

把 SAP 配置当成一张地图:用 IMG 把实施、变更与治理串成一条清晰的路

摘要 SAP IMG(Implementation Guide)是SAP实施的核心导航体系,它将客户需求转化为系统配置,提供结构化路径和文档化支持。IMG不是简单的菜单树,而是包含业务落地路径、标准化配置活动和文档化知识的实施语言。通过三种视图(Reference、Enterprise、Project)解决不同管理问题,其中Project IMG尤其重要,可管理项目范围、分工和进度。实际工作中应通过SPRO事务码访问IMG,将探索与执行分开管理。案例显示,跨国企业通过Project IMG可有效控制组织架构

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 226

哈希表(散列表)基础知识总结

目录 1.散列表概述 1.1散列表查找定义 1.2散列表查找步骤 2.散列函数的构造方法 2.1直接定址法 2.2数字分析法 2.3平方取中法 2.4折叠法 2.5除留余数法 2.6随机数法 3.处理散列冲突的方法 3.1开放定址法 3.2再散列函数法 3.3链地址法 3.4公共溢出区法 4.散列表查找实现 4.1散列表查找算法实现 4.2散列表查找性能分析 ...

qq_40692109的博客 2542

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

算法设计与分析——散列表/哈希表(Hash Table)(一):基础知识

许多应用都需要一种动态集合结构,它至少要支持插入、删除和查找字典操作。 例如,用于程序语言编译的编译器维护了一个符号表,其中元素的关键字为任意字符串,它与程序中的标识符相对应。散列表是实现字典操作的一种有效数据结构。尽管最坏情况下散列表中查找一个元素的时间与链表中查找的时间相同,达到了O(n)O(n)O(n)。然而在实际应用中,散列查找的性能是极好的。在一些合理的假设下,在散列表中查找一个元素的平均时间是O(1)O(1)O(1)。 散列表是普通数组概念的推广。由于对普通数组可以直接寻址,使得能在O(1)O(

冯·诺依曼 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

哈希表(散列表)必备基础知识

数据结构-查找-哈希表(散列表)查找-科班学习笔记 本篇是查找第三篇,需要第一篇基本概念的基础,请前往 查找1 目录数据结构-查找-哈希表(散列表)查找-科班学习笔记哈希表哈希表的设计直接定址法除留余数法数字分析法哈希冲突的解决方法开放定址法线性探查法:平方探查法拉链法哈希查找 哈希表 哈希表是一种存储结构,它是一定长度的连续内存单元,它并未适合任何情况,主要适合记录的关键字与存储地址存在某种函...

JunsIr的技术栈 1435

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

算法数据结构基础——哈希表(Hash Table)

哈希表(Hash Table):也叫做散列表。是根据关键码值(Key Value)直接进行访问的数据结构。哈希表通过「键key」和「映射函数Hash(key)」计算出对应的「值value」,把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做「哈希函数(散列函数)」,存放记录的数组叫做「哈希表(散列表)」。哈希表的关键思想是使用哈希函数,将键key映射到对应表的某个区块中。向哈希表中插入一个关键码值:哈希函数决定该关键字的对应值应该存放到表中的哪个区块,并将对应值存放到该区块中。

白话机器学习 3万+

散列表,也就是哈希表的有关基础知识点

散列表,也就是哈希表的有关基础知识点

qq_43118674的博客 189

Day5 哈希表part01 哈希表基础

哈希表大小(tablesize)时,会出现几个数值同时映射到相同索引下标的情况,这时候需要引出。这里只进行了简单的概念引入。后期会对其进行更加具体的解释和计算方法对本片文章进行补充。使用更多的tablesize,将冲突位置的数值放在下一位索引下标。判断一个元素是否会出现在集合中。此篇文章大量引入代码随想录,感兴趣的同学可以去这里学习。以下是C++中set和map的三种数据结构。的值而直接进行访问的数据结构。将相同索引位置下标的数值,使用。哈希表,也称作散列表。直接访问数组中元素。

weixin_54010693的博客 1310

散列表基础及其设计

于是我们就顺序地往后一个一个找,看有没有空闲的位置,遍历到尾部都没有找到空闲的位置,于是我们再从表头开始找,直到找到空闲位置 2,于是将其插入到这个位置。,跟线性探测很像,线性探测每次探测的步长是 1,那它探测的下标序列就是 hash(key)+0,hash(key)+1,hash(key)+2……否则就顺序往后依次查找。对于动态散列表,随着数据的删除,散列表中的数据会越来越少,空闲空间会越来越多。当通过参赛编号查询选手信息的时候,我们用同样的方法,取参赛编号的后两位,作为数组下标,来读取数组中的数据。

2301_81948543的博客 1158

哈希表-哈希表理论基础

哈希表-哈希表理论基础

m0_72900498的博客 1215

算法基础—哈希表散列表的构建和处理冲突

算法基础—哈希表散列表的构建和处理冲突

null_one的博客 1022

数据结构:哈希表(散列表)基础

哈希表(散列表)基础 引入哈希表 什么是哈西表:   一种具有相同特性的数据元素的集合,每个元素具有唯一标识自己的关键字。 基本原理:   说明:     顺序查找、二分查找或者二叉树的查找是基于待查关键字与表中元素的关键字进行比较而实现的查找方法。     散列查找是通过计算哈希函数来得到待查关键字的地址,...

weixin_30807677的博客 418

Runtime学习基础之class结构之散列表(哈希表)

上次我们学习runtime的isa,这节课我们继续学习runtime的class结构,这个博客我们主要说class的cache_t cache这个散列表(哈希表),主要是为了让我们更深刻的理解调用过程,通过这个博客,你将学习到: 通过Runtime调用对象方法的过程的更深刻的理解 我们以前如果面试官问你,一个对象调用对象方法的过程是什么样的?你可能会回答:instance通过isa找到类对象,然后调用对象方法,如果找不到就通过superclass找到父类寻找instance方法....通过这个博客,你就

Lucky_Deng的博客 376

散列表/哈希表的基础知识(上)

散列的基本概念 【例子】现有11个数,分别是18,23,11,20,2,7,27,30,42,15,34。现定义一个函数h(key) = key mod 17。分别把这11个数存储到大小为17的整型数组(散列表)中。其结果为: 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表

哆啦A瑶的博客 807

【数据结构基础】散列表存储

散列表

正心 诚意 修身 2339
上一篇: 力扣.三数之和/四数之和
下一篇: 力扣刷题之排序链表
旺仔 小馒头
博客等级 码龄6年 12粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值