数据结构 散列表 学习 2025年6月12日15:30:48

数据结构 散列表

哈希表(Hash Table):

通过哈希函数将键(key)映射到存储位置,从而实现快速的插入、删除和查找操作。

哈希表是现代编程中最重要的数据结构之一,几乎所有编程语言都提供了内置实现。

计数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define TABLE_SIZE 100  // 哈希表大小// 哈希表节点结构
typedef struct Node {int key;          // 存储的元素值int count;        // 出现次数struct Node* next; // 链表指针(处理冲突)
} Node;// 创建新节点
Node* createNode(int key) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->key = key;newNode->count = 1;newNode->next = NULL;return newNode;
}// 简单哈希函数
unsigned int hash(int key) {return key % TABLE_SIZE;
}// 插入元素到哈希表
void insert(Node* hashTable[], int key) {unsigned int index = hash(key);// 检查是否已存在Node* current = hashTable[index];while (current != NULL) {if (current->key == key) {current->count++; // 已存在,计数增加return;}current = current->next;}// 不存在,创建新节点Node* newNode = createNode(key);newNode->next = hashTable[index];hashTable[index] = newNode;
}// 打印哈希表内容
void printHashTable(Node* hashTable[]) {for (int i = 0; i < TABLE_SIZE; i++) {Node* current = hashTable[i];while (current != NULL) {printf("元素 %d 出现次数: %d\n", current->key, current->count);current = current->next;}}
}// 释放哈希表内存
void freeHashTable(Node* hashTable[]) {for (int i = 0; i < TABLE_SIZE; i++) {Node* current = hashTable[i];while (current != NULL) {Node* temp = current;current = current->next;free(temp);}}
}int main() {Node* hashTable[TABLE_SIZE] = {NULL}; // 初始化哈希表int nums[] = {1, 2, 3, 2, 1, 3, 3, 4, 5, 4, 4, 4};int size = sizeof(nums) / sizeof(nums[0]);// 统计每个元素的出现次数for (int i = 0; i < size; i++) {insert(hashTable, nums[i]);}// 打印统计结果printHashTable(hashTable);// 释放内存freeHashTable(hashTable);return 0;
}

哈希函数:将任意大小的数据映射到固定大小的值(哈希值)

#include <stdio.h>
#include <string.h>// 简单哈希函数 - 适用于字符串
unsigned int simple_hash(const char* str) {unsigned int hash = 0;while (*str) {hash = (hash * 31) + *str; // 31是个常用质数str++;}return hash;
}// 测试
int main() {const char* str1 = "hello";const char* str2 = "world";printf("'%s' 的哈希值: %u\n", str1, simple_hash(str1));printf("'%s' 的哈希值: %u\n", str2, simple_hash(str2));return 0;
}

桶(Bucket):存储数据的容器,通常是一个数组

冲突(Collision):不同键映射到相同哈希值的情况

滚动哈希:一种高效处理字符串/数组子串哈希的技术,常用于字符串匹配、重复子串检测等场景

#include <stdio.h>
#include <string.h>#define BASE 256  // 基数,通常选择质数
#define MOD 101   // 模数,通常选择大质数// 计算初始哈希值
unsigned long initial_hash(const char* str, int len) {unsigned long hash = 0;for (int i = 0; i < len; i++) {hash = (hash * BASE + str[i]) % MOD;}return hash;
}// 滚动哈希计算下一个哈希值
unsigned long roll_hash(unsigned long prev_hash, char left_char, char right_char, int len, unsigned long power) {prev_hash = (prev_hash + MOD - (left_char * power) % MOD) % MOD;return (prev_hash * BASE + right_char) % MOD;
}// 查找模式串在文本中的位置
void rabin_karp(const char* text, const char* pattern) {int n = strlen(text);int m = strlen(pattern);if (m == 0 || n < m) return;// 计算BASE^(m-1) % MODunsigned long power = 1;for (int i = 0; i < m - 1; i++) {power = (power * BASE) % MOD;}unsigned long pattern_hash = initial_hash(pattern, m);unsigned long text_hash = initial_hash(text, m);for (int i = 0; i <= n - m; i++) {if (text_hash == pattern_hash) {// 哈希匹配,验证实际字符串是否匹配if (strncmp(text + i, pattern, m) == 0) {printf("在位置 %d 找到匹配\n", i);}}// 滚动到下一个位置if (i < n - m) {text_hash = roll_hash(text_hash, text[i], text[i + m], m, power);}}
}int main() {const char* text = "ABABDABACDABABCABAB";const char* pattern = "ABABCABAB";rabin_karp(text, pattern);return 0;
}

哈希工作原理

插入数据时 计算哈希值  确定储存位置

查找数据时 计算哈希值  直接访问对应位置

处理冲突时

                链接地址法 每个桶使用链表 储存多个元素

                开放寻址法 寻找下一个可用位置

应用场景

  • 数据库索引

  • 缓存实现(如Redis)

  • 语言中的字典/映射结构(如Python的dict,Java的HashMap)

  • 唯一性检查

优缺点

优点

  • 平均情况下操作非常快

  • 实现简单直接

缺点

  • 哈希函数设计影响性能

  • 冲突处理增加复杂度

  • 不支持有序遍历(除非使用特殊实现)

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

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

相关文章

数据结构之LinkedList

系列文章目录 数据结构之ArrayList-CSDN博客 目录 系列文章目录 前言 一、模拟实现链表 1. 遍历链表 2. 插入节点 3. 删除节点 4. 清空链表 二、链表的常见操作 1. 反转链表 2. 返回链表的中间节点 3. 链表倒数第 k 个节点 4. 合并两个有序链表 5. 分割链表 6. 判…

DC3靶机渗透

1. 靶机介绍 主要的内容有 sql 注入漏洞、joomla 框架漏洞、ssh 攻击、shell 反弹、提权 信息收集(ip、端口、目录、指纹信息)--->利用漏洞--->反弹---->提权 2. 信息收集 2.1. 扫描存活 ip 192.168.220.134 2.2. 端口扫描 nmap -T4 -A -p- 192.168.220.134 …

C# 线程交互

一、为什么要进行线程交互 在C#中&#xff0c;线程交互通常涉及到多个线程之间的数据共享和同步。‌. 一、全局变量 在C#中&#xff0c;全局变量是指在程序的任何地方都可以访问的变量。通常&#xff0c;全局变量是在类的外部定义的&#xff0c;或者在所有方法之外定义的。全…

Cursor 编辑器中的 Notepad 功能使用指南

Cursor 编辑器中的 Notepad 功能使用指南 摘要 本指南全面介绍了 Cursor 编辑器中的 Notepad 功能&#xff0c;涵盖其用途、多种访问方式、适用场景以及与其它功能的整合技巧等内容&#xff0c;助力用户高效利用该功能提升工作流程效率。 不同访问方式介绍 功能概述 Curso…

用于评估大语言模型(LLMs)能力的重要基准任务(Benchmark)

基准任务涵盖了 多领域&#xff08;如语言理解、数学、推理、编程、医学等&#xff09;和 多能力维度&#xff08;如事实检索、计算、代码生成、链式推理、多语言处理&#xff09;。常用于模型发布时的对比评测&#xff0c;例如 GPT-4、Claude、Gemini、Mistral 等模型的论文或…

力扣HOT100之技巧:169. 多数元素

这道题如果不考虑空间复杂度和时间复杂度的限制的话很好做&#xff0c;一种思路是通过一次遍历将所有元素的数量记录在一个哈希表中&#xff0c;然后我们直接返回出现次数最多的键即可。另一种思路是直接对数组进行排序&#xff0c;数组中间的值一定是多数元素&#xff0c;因为…

wordpress首页调用指定ID页面内的相册

要在WordPress首页调用ID为2的页面中的相册&#xff0c;你可以使用以下几种方法&#xff1a; 方法一&#xff1a;使用短代码和自定义查询 首先&#xff0c;在你的主题的functions.php文件中添加以下代码&#xff1a; function display_page_gallery($atts) {$atts shortcod…

基于深度学习的异常检测系统:原理、实现与应用

前言 在现代数据驱动的业务环境中&#xff0c;异常检测&#xff08;Anomaly Detection&#xff09;是一个关键任务&#xff0c;它能够帮助企业和组织及时发现数据中的异常行为或事件&#xff0c;从而采取相应的措施。异常检测广泛应用于金融欺诈检测、网络安全、工业设备故障监…

Java基于BS架构的OA流程可视化实战:从工作流引擎到前端交互(附完整源代码+论文框架)

一、引言&#xff1a;BS架构OA系统的流程可视化需求 在企业信息化建设中&#xff0c;基于浏览器/服务器&#xff08;BS&#xff09;架构的OA系统通过流程自动化提升办公效率&#xff0c;而流程可视化是实现流程监控、优化的核心模块。本文基于Java技术栈&#xff0c;结合Activ…

JavaWeb-数据库连接池

目录 1.springboot默认Hikari(追光者)连接池 2.切换为Druid(德鲁伊)连接池 1.springboot默认Hikari(追光者)连接池 2.切换为Druid(德鲁伊)连接池 一般几乎用不到&#xff0c;不需要切换 <!--Druid连接池--> <dependency><groupId>com.alibaba</groupId&…

c# 完成恩尼格玛加密扩展

c# 完成恩尼格玛加密扩展 恩尼格玛扩展为可见字符恩尼格玛的设备原始字符顺序转子的设置反射器的设置连接板的设置 初始数据的设置第一版 C# 代码第二版 C# 代码 总结 恩尼格玛 在之前&#xff0c;我们使用 python 实现了一版恩尼格玛的加密算法&#xff0c;但是这一版&#x…

【Redisson】锁可重入原理

目录 一、基本原理 二、源码解析&#xff1a; &#xff08;2&#xff09;获取锁 &#xff08;1&#xff09;释放锁&#xff1a; 之前给大家介绍过redisson的分布式锁&#xff0c;用redisson来实现比自己手搓简单的分布式锁有很多好处&#xff0c;因为这些可重入、可重试的逻…

BERT 模型微调与传统机器学习的对比

BERT 微调与传统机器学习的区别和联系&#xff1a; 传统机器学习流程 传统机器学习处理文本分类通常包含以下步骤&#xff1a; 特征工程&#xff1a;手动设计特征&#xff08;如 TF-IDF、词袋模型&#xff09;模型训练&#xff1a;使用分类器&#xff08;如 SVM、随机森林、逻…

(12)-Fiddler抓包-Fiddler设置IOS手机抓包

1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求&#xff0c;也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler 能捕获Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。同理也可以截获iOS设备发出的请求&#xff0c;比如 iPhone、iPad 和 MacBook 等苹…

芯科科技Tech Talks技术培训重磅回归:赋能物联网创新,共筑智能互联未来

聚焦于Matter、蓝牙、Wi-Fi、LPWAN、AI/ML五大热门无线协议与技术 为年度盛会Works With大会赋能先行 随着物联网&#xff08;IoT&#xff09;和人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;越来越多的企业和个人开发者都非常关注最新的无线连接技术和应用…

docker-compose容器单机编排

docker-compose容器单机编排 开篇前言 随着网站架构的升级&#xff0c;容器的使用也越来越频繁&#xff0c;应用服务和容器之间的关系也越发的复杂。 这个就要求研发人员能更好的方法去管理数量较多的服务器&#xff0c;而不能手动挨个管理。 例如一个LNMP 架构&#xff0c;就…

LeetCode--29.两数相除

解题思路&#xff1a; 1.获取信息&#xff1a; 给定两个整数&#xff0c;一个除数&#xff0c;一个被除数&#xff0c;要求返回商&#xff08;商取整数&#xff09; 限制条件&#xff1a;&#xff08;1&#xff09;不能使用乘法&#xff0c;除法和取余运算 &#xff08;2&#…

中山大学GaussianFusion:首个将高斯表示引入端到端自动驾驶多传感器融合的新框架

摘要 近年来由于端到端自动驾驶极大简化了原有传统自动驾驶模块化的流程&#xff0c;吸引了来自工业界和学术界的广泛关注。然而&#xff0c;现有的端到端智驾算法通常采用单一传感器&#xff0c;使其在处理复杂多样和具有挑战性的驾驶场景中受到了限制。而多传感器融合可以很…

《哈希算法》题集

1、模板题集 满足差值的数字对 2、课内题集 字符统计 字符串统计 优质数对 3、课后题集 2006 Equations k倍区间 可结合的元素对 满足差值的数字对 异常频率 神秘数对 费里的语言 连连看 本题集为作者&#xff08;英雄哪里出来&#xff09;在抖音的独家课程《英雄C入门到精…

Cordova移动应用对云端服务器数据库的跨域访问

Cordova移动应用对云端服务器数据库的跨域访问 当基于类似 Cordova这样的跨平台开发框架进行移动应用的跨平台开发时&#xff0c;往往需要访问部署在公网云端服务器上的数据库&#xff0c;这时就涉及到了跨域数据访问的问题。 文章目录 Cordova移动应用对云端服务器数据库的跨…