数组索引哈希表(Array Indexed Hash Table)

数组索引哈希表(Array Indexed Hash Table)

哈希表:散列表,通过建立key与value之间的映射关系,实现高效的元素查询。

哈希表的抽象表示

哈希表,数组,链表的查询效率

  1. 数组
    • 查询效率:对于已知索引的位置,数组提供的是常数时间复杂度 O(1) 的查询速度,这是最快的。数组通过下标直接访问,无需遍历。
    • 注意:如果进行的是顺序查找(比如查找特定值而不是索引),则数组的查询效率降为线性时间复杂度 O(N),需要遍历整个数组。
  2. 链表
    • 查询效率:链表的查询效率通常较低,因为它们不具备随机访问特性。在单链表中,为了找到某个特定元素,必须从头结点开始沿着指针逐个遍历节点,其查询时间复杂度为 O(N),其中 N 是链表中元素的数量。
  3. 哈希表
    • 查询效率:哈希表的理想查询时间复杂度也是 O(1),这是基于理想哈希函数的前提下,能够将输入的关键字均匀地映射到哈希表的不同槽位,且没有冲突发生。当发生哈希冲突并采用链地址法解决冲突时(例如Java中的HashMap),即使存在冲突,只要哈希函数设计得较好,实际查询性能仍然接近 O(1)。
    • 实际上,随着哈希表负载因子增大,冲突概率增加,查询性能可能会退化至接近 O(N),但一般情况下,好的哈希函数配合动态调整大小等机制,能将这种影响降到最低。

哈希表的常用操作

在这里插入图片描述

哈希表的遍历:(c++/java)

/* 遍历哈希表 */
// 遍历键值对 key->value
for (auto kv: map) {cout << kv.first << " -> " << kv.second << endl;
}
// 使用迭代器遍历 key->value
for (auto iter = map.begin(); iter != map.end(); iter++) {cout << iter->first << "->" << iter->second << endl;
}
/* 遍历哈希表 */
// 遍历键值对 key->value
for (Map.Entry <Integer, String> kv: map.entrySet()) {System.out.println(kv.getKey() + " -> " + kv.getValue());
}
// 单独遍历键 key
for (int key: map.keySet()) {System.out.println(key);
}
// 单独遍历值 value
for (String val: map.values()) {System.out.println(val);
}

数组实现哈希散列(通俗易懂)

在哈希表中,我们将数组中的每个空位称为桶(bucket),每个桶可存储一个键值对。因此,查询操作就是找到 key 对应的桶,并在桶中获取 value

哈希函数工作原理

  1. 当向哈希表插入一个键值对 (key, value) 时,首先会使用哈希函数计算出 key 的哈希值,该哈希值通常会经过某种处理以适应数组的索引范围。
  2. 计算得到的索引对应的数组位置就是一个“桶”。如果该“桶”为空,则直接将键值对存入;如果不为空,且仅有一个元素(即没有哈希冲突),则同样直接存放;若已有多个元素(发生了哈希冲突),则可能采用链地址法(linked list)或开放寻址法等方式解决冲突,即将新的键值对添加到该“桶”内适当的位置。
  3. 在查询操作时,我们同样使用哈希函数计算待查询 key 的哈希值,然后根据此哈希值找到相应的“桶”。
  4. 查找“桶”后,如果桶内只有一个元素,或者可以直接找到匹配的 key,那么就可以立即返回对应的 value。如果桶内有多个元素(因哈希冲突),则需要进一步在桶内进行查找,直到找到匹配的 key 或确定不存在为止。

哈希函数

####是一种特殊的数学函数,接受任意长度的输入(通常是字符串或者其他类型的数据),通过一定的算法将其转化为固定长度的输出,这个输出的值通常被称为哈希值(Hash Value) ,散列值或者消息摘要。

哈希函数的主要特点包括:

  1. 唯一性(尽可能):不同的输入应该产生不同的输出,理想的哈希函数使得任何两个不同的输入映射到同一个输出的概率极低。
  2. 确定性:相同的输入总是会产生相同的输出。
  3. 固定长度输出:不论输入数据的大小如何变化,哈希函数产生的输出长度都是固定的。
  4. 不可逆性:一个好的哈希函数应当很难通过其输出反推回原始输入,也就是说它是非对称、不可逆的。
  5. 雪崩效应:输入数据稍作改动,输出的哈希值应该会有很大变化,这样即便两个输入很相近,它们的哈希值也应该看起来毫无关联。

###在计算机科学和密码学中,哈希函数有多种应用场景,如:

  • 数据完整性验证:通过计算文件或数据块的哈希值,可以在传输前后比较哈希值来确认数据是否被篡改。
  • 密码存储:在安全领域,用户的密码通常不会明文存储,而是存储其哈希值,并结合盐值(salt)防止彩虹表攻击。
  • 数据索引:在数据结构如哈希表中,哈希函数用于快速定位数据项在表中的位置,实现高效查找和插入操作。
  • 区块链技术:在比特币和其他加密货币中,哈希函数用于生成区块哈希,确保交易的安全性和账本的一致性。

哈希表(Hash Table) 在编程中,哈希函数用于创建和查询哈希表。例如,假设我们有一个简单的电话簿程序,需要快速查找联系人姓名对应的电话号码。

  • 假设我们设计了一个简单的哈希函数 hash(key),它接受一个字符串作为键(即姓名),并返回一个整数索引。
  • 当添加新的联系人时,我们首先使用哈希函数计算姓名的哈希值,然后将其存入相应索引的位置(如果发生冲突,则采用解决冲突的方法如链地址法或开放寻址法)。
  • 查找联系人时,同样对姓名应用哈希函数获取索引,然后从哈希表中对应位置找到电话号码。

密码存储 在用户注册系统中,不直接存储用户的密码原文,而是存储密码经过哈希运算后的值。当用户登录时,系统会对用户输入的密码做同样的哈希运算,然后与数据库中存储的哈希值进行比对。

例如:

  • 用户设定的密码是 "MyP@ssword123"
  • 系统使用一个强壮的哈希函数(如bcrypt或argon2)对该密码进行处理,得到哈希值 "$2b$12$SgVQ2yvYDqJZ..jRrUH/wO/gpGzWU/ExXQo8A.ylXNldtKwQZI/" 并存储此值。
  • 当用户下次登录时,输入相同密码 "MyP@ssword123",系统再次应用同一哈希函数并检查生成的哈希值是否与存储值匹配。

代码实现

/* 键值对 */
struct Pair {public:int key;string val;Pair(int key, string val) {this->key = key;this->val = val;}
};/*构造函数 Pair(int key, string val):这是结构体的一个成员函数,用于初始化新创建的Pair实例。当通过Pair构造函数创建一个新对象时,需要传入一个整数和一个字符串作为参数。构造函数内部通过this->key = key; 和 this->val = val;语句将传入的实参赋值给结构体内的成员变量。*//* 基于数组实现的哈希表 */
class ArrayHashMap {private:vector<Pair *> buckets;public:ArrayHashMap() {// 初始化数组,包含 100 个桶buckets = vector<Pair *>(100);}~ArrayHashMap() {// 释放内存for (const auto &bucket : buckets) {delete bucket;}buckets.clear();}/* 哈希函数 */int hashFunc(int key) {int index = key % 100;return index;}/* 查询操作 */string get(int key) {int index = hashFunc(key);Pair *pair = buckets[index];if (pair == nullptr)return "";return pair->val;}/* 添加操作 */void put(int key, string val) {Pair *pair = new Pair(key, val);int index = hashFunc(key);buckets[index] = pair;}/* 删除操作 */void remove(int key) {int index = hashFunc(key);// 释放内存并置为 nullptrdelete buckets[index];buckets[index] = nullptr;}/* 获取所有键值对 */vector<Pair *> pairSet() {vector<Pair *> pairSet;for (Pair *pair : buckets) {if (pair != nullptr) {pairSet.push_back(pair);}}return pairSet;}/* 获取所有键 */vector<int> keySet() {vector<int> keySet;for (Pair *pair : buckets) {if (pair != nullptr) {keySet.push_back(pair->key);}}return keySet;}/* 获取所有值 */vector<string> valueSet() {vector<string> valueSet;for (Pair *pair : buckets) {if (pair != nullptr) {valueSet.push_back(pair->val);}}return valueSet;}/* 打印哈希表 */void print() {for (Pair *kv : pairSet()) {cout << kv->key << " -> " << kv->val << endl;}}
};

##注意事项:

哈希函数的设计至关重要,它直接影响着哈希表的性能和空间利用率。
解决哈希冲突的策略会影响哈希表在高负载条件下的表现和内存使用效率。
安全考量:

在一些安全敏感的应用中(如密码存储),哈希函数不仅需要速度快,还需要具备足够的随机性和不可预测性,以抵抗碰撞攻击和预计算攻击

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

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

相关文章

HackMyVM-suidy

目录 信息收集 arp nmap WEB web信息收集 gobuster 目录批量查看 hydra ssh连接 提权 系统信息收集 提权 信息收集 arp ┌─[rootparrot]─[~/HackMyVM] └──╼ #arp-scan -l Interface: enp0s3, type: EN10MB, MAC: 08:00:27:16:3d:f8, IPv4: 192.168.9.115 St…

Spring Boot统一功能处理(一)

本篇主要介绍Spring Boot的统一功能处理中的拦截器。 目录 一、拦截器的基本使用 二、拦截器实操 三、浅尝源码 初始化DispatcherServerlet 处理请求&#xff08;doDispatch) 四、适配器模式 一、拦截器的基本使用 在一般的学校或者社区门口&#xff0c;通常会安排几个…

一夜爆红的4款国产软件,却一度被大众误以为是外国人开发

在现今高度信息化的时代&#xff0c;计算机已经深深地渗透到了我们生活的每一个角落。 从日常的办公学习到娱乐休闲&#xff0c;几乎都离不开计算机技术的支持。而在这背后&#xff0c;软件作为计算机的灵魂&#xff0c;其发展历史可谓波澜壮阔。 中国软件产业经过多年的积累和…

Linux 安装KVM虚拟机

什么是KVM虚拟机&#xff1f; KVM 是 Kernel-based Virtual Machine 的缩写&#xff0c;是一种用于虚拟化的开源硬件虚拟化技术。它使用 Linux 内核的虚拟化模块&#xff0c;将物理服务器划分为多个虚拟机。KVM 允许虚拟机直接访问物理硬件资源,从而提供出色的性能和稳定性,同…

基于二级片内硬件堆栈的后向CFI 验证方法研究,第5章 测试及实验结果

5.1 SoC系统功能仿真 按照上一章的设计方案&#xff0c;采用verilog HDL语言&#xff0c;在玄铁E906处理器平台中分别采用延迟验证和批处理验证方法完成了二级硬件堆栈的RTL级硬件描述。为了验证二级硬件堆栈的正确性&#xff0c;采用斐波那契数列进行验证&#xff0c;设置RAB…

【R语言】组合图:散点图+箱线图+平滑曲线图+柱状图

用算数运算符轻松组合不同的ggplot图&#xff0c;如图&#xff1a; 具体代码如下&#xff1a; install.packages("devtools")#安装devtools包 devtools::install_github("thomasp85/patchwork")#安装patchwork包 library(ggplot2) library(patchwork) #p1是…

AMPLE: 基于图简化和增强图表征学习的漏洞检测

GNN已被证实能有效学习源代码的图表示&#xff0c;然而GNN难以处理代码结构图中长距离节点之间连接的局限性&#xff0c;导致无法捕获代码图的全局信息&#xff08;即远距离节点间的依赖关系&#xff09;。针对上述问题&#xff0c;提出漏洞检测框架AMPLE&#xff0c;它包括图简…

机器学习引领金融革命:重塑金融服务领域新格局,开启智能化新篇章

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

我们一起看看《看漫画学C++》中如何介绍的字符串的用法

C中的字符串使用的是 std::string 类型&#xff0c;它是C标准库中提供的字符串类&#xff0c;提供了丰富的字符串操作方法。下面是关于C字符串的一些常用用法&#xff1a; 字符串拼接 字符串查找 字符串追加 购书地址&#xff1a;https://item.jd.com/14418856.html

【教程】一个比较良心的C++代码混淆器

这是一个比较良心的C代码混淆器&#xff0c;用于信息竞赛训练和保护代码免受抄袭。本文将介绍这个混淆器的使用方法、混淆效果和已知的一些bug。同时&#xff0c;我们也会给出一些示例来演示混淆器的具体操作。 引言 在信息竞赛训练和实际开发中&#xff0c;保护代码的安全性和…

Docker 学习笔记(十):Centos7 中 Docker 部署 Redis 集群,打包 SpringBoot 微服务

一、前言 记录时间 [2024-4-17] 系列文章简摘&#xff1a; Docker 学习笔记&#xff08;六&#xff09;&#xff1a;挑战容器数据卷技术一文通&#xff0c;实战多个 MySQL 数据同步&#xff0c;能懂会用&#xff0c;初学必备 Docker 学习笔记&#xff08;七&#xff09;&#x…

关于外网后端服务访问内网minio中间件,因连接minio超时,启动失败问题

注&#xff1a;服务器情况&#xff1a;2台服务器&#xff0c;内网服务器包含&#xff08;activemq、minio、nginx、redis、mysql、后端java服务&#xff09;。外网服务器只有后端java服务&#xff0c;访问内网的中间件&#xff08;内网服务器开放了部分指定端口&#xff09; 问…

web安全学习笔记(9)

记一下第十三课的内容。 准备工作&#xff1a;在根目录下创建template目录&#xff0c;将login.html放入其中&#xff0c;在该目录下新建一个reg.html。在根目录下创建一个function.php 一、函数声明与传参 PHP中的函数定义和其他语言基本上是相同的。我们编辑function.php …

【C++】哈希

1. unordered系列关联式容器 STL提供了底层为红黑树结构的一系列关联式容 这里介绍 unordered_set 和 unordered_map a. unordered_map unordered_map 是存储<key, value>键值对的关联式容器&#xff0c;其允许通过 key 快速的索引到与 其对应的 value unordered_m…

nested exception is dm.jdbc.driver.DMException: 字符串截断

nested exception is dm.jdbc.driver.DMException: 字符串截断 背景问题分析问题解决 背景 今天在日常工作中遇到了一个问题&#xff0c;正常的 insert into操作报错了 ### Cause: dm.jdbc.driver.DMException: 字符串截断 ; 字符串截断; nested exception is dm.jdbc.driver…

element-ui container 组件源码分享

今日简单分享 container 组件的源码实现&#xff0c;从以下两个方面来讲解&#xff1a; 1、container 组件的页面结构 2、container 组件的属性 一、container 组件的页面结构 二、container 组件的属性 1、container 部分的 direction 属性&#xff0c;子元素的排列方向&am…

Redis(哨兵模式)

什么是哨兵机制 问题: redis 主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工进行主从切换, 同时大量客户端需要被通知切换到新的主节点上, 对于有一定规模的应用来说, 对于人力的资源消耗会很大.解决: 通过哨兵对主从结构进行监控, 一旦出现主节点挂了的情况, 自动…

利用CSS延迟动画,打造令人惊艳的复杂动画效果!

动画在前端开发中是经常遇到的场景之一&#xff0c;加入动画后页面可以极大的提升用户体验。 绝大多数简单的动画场景可以直接通过CSS实现&#xff0c;对于一些特殊场景的动画可能会使用到JS计算实现&#xff0c;通过本文的学习&#xff0c;可以让你在一些看似需要使用JS实现的…

网络编程(现在不重要)

目录 网络编程三要素与InetAddress类的使用 软件架构 面临的主要问题 网络编程三要素&#xff08;对应三个问题&#xff09; InetAddress的使用 TCP与UDP协议剖析与TCP编程案例&#xff08;了解&#xff09; TCP协议 UDP协议 例子 UDP、URL网络编程 URL&#xff1a;&…

求奖金(if)(C语言)

一、N-S流程图&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int I 0;float bonus 0;//提示用户&#xff1b;printf("请输入利润I&#xff1a;");//获取用户值&#xf…