夏驰和徐策带你从零开始学数据结构——哈希表
哈希表的概念:
哈希表是一种常用的数据结构,它可以在 O(1) 的时间复杂度内执行插入、查找和删除操作。哈希表的核心思想是使用哈希函数将键值对映射到数组中的一个位置上,从而实现快速的访问和修改。
哈希表由两个主要部分组成:哈希函数和数组。哈希函数将键映射到数组的下标,而数组则用来存储键值对。当需要访问或修改某个键值对时,只需要使用哈希函数将键转换为数组下标,然后访问或修改对应的位置即可。
使用哈希表的关键在于设计一个好的哈希函数,它应该满足以下几个要求:
- 一致性:同一个键总是映射到相同的数组下标。
- 均匀性:尽可能地使键被映射到不同的数组下标上,从而减少哈希冲突的概率。
- 高效性:计算哈希值的时间应该尽量短,以保证操作的高效性。
解决哈希冲突的方法有多种,常用的有链表法和开放地址法。链表法是在每个数组元素上维护一个链表,当哈希冲突发生时,将新的键值对插入到链表中。开放地址法则是尝试在其他空闲的位置上插入键值对,比如线性探测、二次探测和双重哈希等。
需要注意的是,哈希表的性能取决于哈希函数的设计和数组的大小。如果哈希函数不好,或者数组太小,就会导致哈希冲突增多,从而降低哈希表的效率。因此,在实际应用中,需要根据具体的场景来设计合适的哈希函数和数组大小,以达到最优的性能。
我的理解:
哈希表是一种用于快速查找和插入的数据结构,其核心思想是通过哈希函数将键映射到数组中的一个位置上。哈希函数将键映射到数组中的位置时,需要满足一致性、均匀性和高效性等要求。具体地说,一致性要求相同的键总是映射到相同的位置上,均匀性要求哈希函数能够尽可能地将键均匀地映射到数组中的位置上,高效性要求计算哈希值的时间尽量短。
哈希表的优点在于其插入、查找和删除的时间复杂度都为 O(1),即常数级别的时间复杂度,因此在需要快速进行这些操作的场合下,哈希表是一种非常有用的数据结构。常用的哈希表实现方式有链表法和开放地址法,其中链表法在哈希冲突时使用链表来存储冲突的键值对,而开放地址法则是尝试在其他空闲的位置上插入键值对。
总的来说,理解哈希表的概念需要掌握哈希函数的设计原理、数组的存储方式和解决哈希冲突的方法等基础知识,以及如何在实际应用中根据具体的场景来选择适合的哈希表实现方式。
例子:
假设我们有一个存储学生信息的数据集合,其中每个学生的信息包括学号、姓名、年龄等。我们需要能够快速地根据学号查找到对应的学生信息。这时,我们可以使用哈希表来实现这个功能。
首先,我们需要设计一个哈希函数,将学号映射到一个数组中的位置上。一种简单的哈希函数可以是取学号的最后几位作为数组下标,比如我们可以取学号的后两位作为下标,那么学号为"20230001"的学生会被映射到数组的第1个位置上,学号为"20230002"的学生会被映射到数组的第2个位置上,以此类推。
接下来,我们可以将每个学生的信息存储到对应的数组位置中。当需要查找某个学生信息时,只需要通过哈希函数计算出该学生信息所在的数组位置,然后访问该位置上的元素即可。
例如,如果我们需要查找学号为"20230001"的学生信息,就可以通过哈希函数将其映射到数组的第1个位置上,然后访问该位置上的元素,即可得到该学生的姓名、年龄等信息。由于哈希表的时间复杂度为 O(1),因此可以在常数级别的时间内完成这个操作,非常高效。
哈希表的实现:
C语言:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define TABLE_SIZE 100// 定义哈希表节点的结构体
typedef struct node {char *key; // 节点的键int value; // 节点的值struct node *next; // 指向下一个节点的指针
} Node;// 定义哈希表的结构体
typedef struct {Node *buckets[TABLE_SIZE]; // 存放哈希桶的数组
} HashTable;// 哈希函数,使用简单的取模法
int hash(char *key) {int hash = 0;for (int i = 0; i < strlen(key); i++) {hash += key[i];}return hash % TABLE_SIZE;
}// 创建一个新节点
Node *create_node(char *key, int value) {Node *node = (Node *) malloc(sizeof(Node));if (node == NULL) {fprintf(stderr, "Error: out of memory\n");exit(1);}node->key = strdup(key); // 使用strdup函数分配内存并复制字符串node->value = value;node->next = NULL;return node;
}// 向哈希表中插入一个节点
void hash_table_insert(HashTable *ht, char *key, int value) {int index = hash(key);Node *node = create_node(key, value);node->next = ht->buckets[index];ht->buckets[index] = node;
}// 在哈希表中查找一个节点
int hash_table_find(HashTable *ht, char *key) {int index = hash(key);Node *node = ht->buckets[index];while (node != NULL) {if (strcmp(node->key, key) == 0) {return node->value;}node = node->next;}return -1; // 表示未找到节点
}// 主函数,测试代码
int main() {HashTable ht;for (int i = 0; i < TABLE_SIZE; i++) {ht.buckets[i] = NULL;}hash_table_insert(&ht, "apple", 1);hash_table_insert(&ht, "banana", 2);hash_table_insert(&ht, "cherry", 3);printf("%d\n", hash_table_find(&ht, "apple")); // 输出 1printf("%d\n", hash_table_find(&ht, "banana")); // 输出 2printf("%d\n", hash_table_find(&ht, "cherry")); // 输出 3printf("%d\n", hash_table_find(&ht, "orange")); // 输出 -1,表示未找到return 0;
}
解释:
这个哈希表使用简单的取模法来计算键的哈希值,将节点插入到对应的哈希桶中,并使用链表解决冲突。在插入和查找节点时,分别使用哈希函数计算出键的哈希值,然后访问对应的哈希桶,遍历链表查找对应的节点。如果找到节点,则返回其值,否则返回-1。
C++实现:
#include <iostream>
#include <string>using namespace std;const int TABLE_SIZE = 100;class HashNode {
public:int key;string value;HashNode* next;HashNode(int key, string value) {this->key = key;this->value = value;this->next = nullptr;}
};class HashMap {
private:HashNode** table;public:HashMap() {table = new HashNode*[TABLE_SIZE];for (int i = 0; i < TABLE_SIZE; i++) {table[i] = nullptr;}}~HashMap() {for (int i = 0; i < TABLE_SIZE; i++) {HashNode* entry = table[i];while (entry != nullptr) {HashNode* prev = entry;entry = entry->next;delete prev;}table[i] = nullptr;}delete[] table;}int getHashCode(int key) {return key % TABLE_SIZE;}void insert(int key, string value) {int hash = getHashCode(key);HashNode* entry = table[hash];if (entry == nullptr) {table[hash] = new HashNode(key, value);} else {while (entry->next != nullptr) {entry = entry->next;}entry->next = new HashNode(key, value);}}string search(int key) {int hash = getHashCode(key);HashNode* entry = table[hash];while (entry != nullptr) {if (entry->key == key) {return entry->value;}entry = entry->next;}return "";}void remove(int key) {int hash = getHashCode(key);HashNode* entry = table[hash];HashNode* prev = nullptr;while (entry != nullptr && entry->key != key) {prev = entry;entry = entry->next;}if (entry == nullptr) {return;}if (prev == nullptr) {table[hash] = entry->next;} else {prev->next = entry->next;}delete entry;}
};int main() {HashMap map;map.insert(1, "apple");map.insert(2, "banana");map.insert(3, "cherry");map.insert(4, "date");cout << map.search(2) << endl; // output: bananamap.remove(3);cout << map.search(3) << endl; // output: (empty string)return 0;
}
解释:
这个示例中,我们定义了一个HashNode类来表示哈希表的节点,它包含了一个键值对和指向下一个节点的指针。我们还定义了一个HashMap类来实现哈希表,它包含了一个指向指针数组的指针,数组的长度为TABLE_SIZE。我们还实现了一些基本操作,如哈希函数的计算、插入、搜索和删除等。
总结:
哈希表的重点:
-
哈希函数的设计:哈希函数需要将键映射到哈希表中的一个位置,使得每个位置都有均匀的分布,并且不同的键能够映射到不同的位置。
-
哈希冲突的处理:哈希冲突是指不同的键映射到了同一个位置,通常有两种处理方式:开放地址法和链表法。开放地址法会寻找哈希表中下一个空闲位置来存储键值对,而链表法会将冲突的键值对组织成一个链表,存储在同一个桶中。
哈希表的难点和易错点:
-
哈希函数的设计需要考虑多种因素,包括键的分布、哈希表的大小和性能等,因此需要具备较强的数学能力和经验。
-
哈希表的性能受到哈希冲突的影响,因此需要合理选择哈希函数和解决冲突的方法,避免出现过多的冲突,降低查询效率。
-
哈希表的空间占用和性能之间存在一定的权衡关系,需要根据具体应用场景和要求进行选择和优化。
-
哈希表的实现需要注意边界条件和特殊情况,比如哈希表为空、键不存在等情况的处理。此外,需要注意哈希函数的输出值需要在哈希表大小范围内。
-
在使用哈希表进行并发操作时,需要考虑线程安全的问题,避免出现竞争条件和数据损坏等情况。

相关文章:
夏驰和徐策带你从零开始学数据结构——哈希表
哈希表的概念: 哈希表是一种常用的数据结构,它可以在 O(1) 的时间复杂度内执行插入、查找和删除操作。哈希表的核心思想是使用哈希函数将键值对映射到数组中的一个位置上,从而实现快速的访问和修改。 哈希表由两个主要部分组成:…...
linux实现网络程序
1️⃣ 在linux下,通过套接字实现服务器和客户端的通信。 2️⃣ 实现单线程、多线程通信。或者实现线程池来通信。 3️⃣ 优化通信,增加守护进程。 有情提醒,类里面默认的函数是内联。内联函数在调用的地方展开,没有函数地址&…...
FreeRTOS 队列(二)
文章目录 一、向队列发送消息1. 函数原型(1)函数 xQueueOverwrite()(2)函数 xQueueGenericSend()(3)函数 xQueueSendFromISR()、xQueueSendToBackFromISR()、xQueueSendToFrontFromISR()(4&…...
用python获取当前目录下的创建时间超过3天的所有python文件
直接上代码: import os import datetime print(os.getcwd()) # 获取当前目录下所有的html文件 html_files [] for filename in os.listdir(): if filename.endswith(.py): html_files.append(os.path.join(., filename)) now date…...
第五章 Linux实际操作——用户管理
第五章 Linux实际操作——用户管理 5.1 基本介绍5.2 添加用户5.3 指定、修改密码5.4 删除用户5.5 查询用户信息指令5.6 切换用户5.7 查看当前用户、登录用户5.8 用户组5.9 用户和组相关文件8.9.1/etc/passwd 文件8.9.2/etc/shadow文件8.9.3/etc/group文件 5.1 基本介绍 Linux系…...
悲观锁和乐观锁详细
悲观锁和乐观锁详细 悲观锁 悲观锁就是悲观的思想,他认为数据每一次被访问的时候都会被上锁,所以每次获得锁的时候都会上锁,这样其他线程想要获取这个锁的时候就会被堵塞,要等待上一个线程锁的释放。也就是说这个线程只一次只…...
三谈ChatGPT(ChatGPT可以解决问题的90%)
这是我第三次谈ChatGPT,前两篇主要谈了ChatGPT的概念,之所以火的原因和对人们的影响,以及ChatGPT可能存在的安全风险和将面临的监管问题。这一篇主要讲讲ChatGPT的场景和处理问题的逻辑。 这一次我特意使用了ChatGPT中文网页版体验了一番。并…...
Qt QSet 详解:从底层原理到高级用法
目录标题 引言:QSet的重要性与简介QSet 的常用接口迭代器:遍历Qset 中的元素(Iterators: Traversing Elements in Qset )高级用法:QSet 中的算法与功能(Advanced Usage: Algorithms and Functions in QList…...
Mac Doxygen的使用
Doxygen的使用 安装着Doxygen和Graphviz这两个东西 在源码目录先使用doxygen -g生成一个叫 ‘Doxyfile’ 的Doxygen的配置文件修改配置文件,里面都有介绍各个选项的功能,这里主要修改一下几个: HAVE_DOT YES EXTRACT_ALL YES EXTRACT_PRIVATE YES E…...
FPGA基础代码复用
一、verilog中有关代码复用的语法 1、连接符“{}” {4{1b1}} 或者 {5d6, 5d8} 2、参数(Parameter)型常量定义 parameter 参数名=表达式; 或者 localparam 参数名=表达式; parameter DATA_WIDTH 20; 3、function函数定义 …...
Hbase简介
HBase简介 一、HBase简介 1. HBase简介 (1) apache的顶级项目,hadoop的数据库,分布式、大规模的大数据存储。 HBase是Google的BigTable的开源java版本,建立在hdfs之上的,分布式、列存储、非关系(nosql、key-value&a…...
科海思除COD树脂,大孔树脂,除COD专用树脂
一、产品介绍 Tulsimer A-722 MP具有控制孔径的大孔强碱性Ⅰ型阴离子交换树脂 Tulsimer A-722 MP 是一款具有便于颜色和有机物去除的控制孔径的,专门开发的大孔强碱性Ⅰ型阴离子交换树脂。 Tulsimer A-722 MP(氯型)专门应用于去除COD…...
Qt 多线程 QThread、QThreadPool使用场景
QThread 和 QRunnable 都是 Qt 框架中用于多线程编程的类,它们之间有以下不同点: 继承关系不同 QThread 继承自 QObject 类,而 QRunnable 没有父类。 实现方式不同 QThread 是一个完整的线程实现,包含了线程的创建、启动、停止、…...
如何一招搞定PCB阻焊过孔问题?
PCB阻焊油墨根据固化方式,阻焊油墨有感光显影型的油墨,有热固化的热固油墨,还有UV光固化的UV油墨。而根据板材分类,又有PCB硬板阻焊油墨,FPC软板阻焊油墨,还有铝基板阻焊油墨,铝基板油墨也可以用…...
【代码随想录】刷题Day2
1.左右指针比大小 977. 有序数组的平方 class Solution { public:vector<int> sortedSquares(vector<int>& nums) {vector<int> ret nums;int left 0;int right nums.size()-1;int end nums.size();while(left<right){if(abs(nums[left])>abs…...
Python机器学习、深度学习技术提升气象、海洋、水文领域实践应用
Python是功能强大、免费、开源,实现面向对象的编程语言,在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能,这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…...
计及调度经济性的光热电站储热容量配置方法【IEEE30节点】(Matlab代码实现)
💥 💥 💞 💞 欢迎来到本博客 ❤️ ❤️ 💥 💥 🏆 博主优势: 🌞 🌞 🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 …...
“不要放过这个春天”解锁品牌春日宣传新玩法
在万物复苏的春天,人们换新装、踏青等需求蓄势待发,出现了全民消费热情高涨的趋势,让品牌「贩卖春天」的宣传此起彼伏。 品牌洞察到用户的消费需求,打造具有品牌特色的浪漫宣传,如采用春日限定元素、创新春天宣传场景…...
利用GPT2 预测 福彩3d预测
使用GPT2预测福彩3D项目 个人总结彩票数据是随机的,可以预测到1-2个数字,但是有一两位总是随机的 该项目紧做模型学习用,通过该项目熟练模型训练调用生成过程. 福彩3D数据下载 https://www.17500.cn/getData/3d.TXT data数据格式 处理后数据格式 每行 2023 03 08 9 7 3 训…...
类加载过程
基本说明 反射机制是Java实现动态语言的关键,也就是通过反射实现类动态加载。 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强动态加载:运行时加载需要的类,如果运行时不用该类,即使…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

