当前位置: 首页 > article >正文

C语言实现对哈希表的操作:创建哈希表与扩容哈希表

一. 简介

前面文章简单了解了哈希表 这种数据结构,文章如下:

什么是哈希表-CSDN博客

本文来学习一下哈希表,具体学习一下C语言实现对哈希表的简单实现。

二. C语言实现对哈希表的操作

1. 哈希表

哈希表(Hash Table,又称散列表)是一种高效的数据结构,用于实现键值对(Key-Value)的存储和快速查找。其核心思想是通过哈希函数将键(Key)映射到数组的特定位置(称为“桶”或“槽”),从而在平均情况下实现接近常数时间复杂度(O(1))的插入、删除和查找操作。

2. C语言实现哈希表操作

(1) 定义哈希表节点结构体与哈希表结构体
#define  HASH_TABLE_LENGTH  20   //链表容量
#define  LOAD_FACTOR        0.85 //负载因子//哈希表节点结构
typedef struct hash_node {char *key; //键int value; //值struct hash_node* next; //下一个节点指针(用于解决冲突)
} hash_node;//哈希表结构
typedef struct hash_table {hash_node** buckets; //桶数组size_t size; //当前元素数量size_t capacity; //哈希表长度
} hash_table;

hash_node结构体表示每个键值对,hash_table表示每个桶,每个桶中存放一个链表。

LOAD_FACTOR宏为负载因子,负载因子是影响哈希表性能的关键指标:

负载因子 = 元素数量 / 容量。

当负载因子超过阈值(如 0.75)时,哈希表会扩容(Resize),以避免冲突过多导致性能下降。

(2) 创建哈希表,扩容哈希表容量
//创建哈希表
hash_table* create_hash_table(void) {hash_table* hash_tables = (hash_table*)malloc(sizeof(hash_table));if(!hash_tables) {printf("hash_table malloc failed!\n");return NULL;}hash_tables->size = 0;hash_tables->capacity = HASH_TABLE_LENGTH;hash_tables->buckets = (hash_node**)calloc(hash_tables->capacity, sizeof(hash_node*));if(!hash_tables->buckets) {printf("hash_tables->buckets calloc failed!\n");return NULL;}return hash_tables;
}//哈希函数的实现(djb2哈希算法)
unsigned long hash_func(const char* str) {unsigned long hash = 5381;int c;while((c = *str++)) {hash = ((hash << 5)+hash)+c;}return hash;
}//调节哈希表长度(扩容)
int resize_hash_table(hash_table* hash_tables, size_t new_capacity) {//分配新桶数组hash_node** new_buckets = (hash_node**)calloc(new_capacity, sizeof(hash_node*));if(!new_buckets) {printf("new_buckets calloc failed!\n");return -1;}int i = 0;//遍历原有桶数组,并重新哈希for(i = 0; i < hash_tables->capacity; i++) {hash_node* node = hash_tables->buckets[i];while(node != NULL) {hash_node* tmp_node = node->next;unsigned long new_index = hash_func(node->key)/ new_capacity;//采用头插入法,插入到新桶中node->next = new_buckets[new_index];new_buckets[new_index] = node;//遍历下一个元素node = tmp_node;}}hash_tables->buckets = new_buckets;hash_tables->capacity = new_capacity;free(hash_tables->buckets);return 0;
}

创建哈希表比较简单,这里不做说明。

调整哈希表容量接口这里进行一下说明:

首先,分配新哈希表的容量。

其次,遍历原来哈希表中所有元素(键值对),将旧的哈希表中元素插入到哈希表新桶中。由于哈希表的容量发生了改变,原有的键值对需要重新计算哈希值并插入到新的哈希表中。

node->next = new_buckets[new_index]; 
new_buckets[new_index] = node;

这两行代码的作用是将当前处理的哈希表节点 node 插入到新哈希表的对应桶(bucket)中,采用的是头插法。

node->next = new_buckets[new_index];
  • 含义:将当前节点 nodenext 指针指向新哈希表中对应桶的头节点。
  • 作用:这一步是为了把当前节点插入到新桶的头部。若新桶原本为空,new_buckets[new_index] 会是 NULL,那么 node->next 就会被设为 NULL;若新桶已经有节点存在,new_buckets[new_index] 就会指向桶中的头节点,此时 node->next 就会指向这个头节点。
new_buckets[new_index] = node;
  • 含义:把新哈希表中对应桶的头节点更新为当前节点 node
  • 作用:经过这一步,当前节点 node 就成为了新桶的头节点。原本新桶中的节点(如果有的话)就变成了 node 的后继节点。

(3) 向哈希表中插入新的键值对

相关文章:

C语言实现对哈希表的操作:创建哈希表与扩容哈希表

一. 简介 前面文章简单了解了哈希表 这种数据结构&#xff0c;文章如下&#xff1a; 什么是哈希表-CSDN博客 本文来学习一下哈希表&#xff0c;具体学习一下C语言实现对哈希表的简单实现。 二. C语言实现对哈希表的操作 1. 哈希表 哈希表&#xff08;Hash Table&#xff…...

MYSQL 常用字符串函数 和 时间函数详解

一、字符串函数 1、​CONCAT(str1, str2, …) 拼接多个字符串。 SELECT CONCAT(Hello, , World); -- 输出 Hello World2、SUBSTRING(str, start, length)​​ 或 ​SUBSTR() 截取字符串。 SELECT SUBSTRING(MySQL, 3, 2); -- 输出 SQ3、LENGTH(str)​​ 与 ​CHAR_LENGTH…...

通过API接口在自己的独立站系统上架商品信息。(实战案例)

以下是一个通过API接口在独立站系统上架商品信息的实战案例&#xff0c;以某跨境电商独立站集成亚马逊产品数据为例&#xff0c;详细说明技术实现流程和关键代码逻辑&#xff1a; 案例背景 某跨境电商独立站需要从亚马逊平台同步商品数据&#xff08;标题、价格、库存、图片、…...

C语言文件操作完全手册:读写·定位·实战

1.什么是文件 1.1文件的概念 文件&#xff08;File&#xff09;是计算机中用于持久化存储数据的基本单位。它可以存储文本、图片、音频、程序代码等各种信息&#xff0c;并在程序运行结束后仍然保留数据。 1.2文件名 一个文件要有一个唯一的文件标识&#xff0c;以便用户识别…...

多模态大语言模型arxiv论文略读(三十七)

A Spectrum Evaluation Benchmark for Medical Multi-Modal Large Language Models ➡️ 论文标题&#xff1a;A Spectrum Evaluation Benchmark for Medical Multi-Modal Large Language Models ➡️ 论文作者&#xff1a;Jie Liu, Wenxuan Wang, Yihang Su, Jingyuan Huan, …...

IDEA创建Gradle项目然后删除报错解决方法

根据错误信息&#xff0c;你的项目目录中缺少Gradle构建必需的核心文件&#xff08;如settings.gradle/build.gradle&#xff09;&#xff0c;且IDEA可能残留了Gradle的配置。以下是具体解决方案&#xff1a; 一、问题根源分析 残留Gradle配置 你通过IDEA先创建了Gradle子模块…...

SpringBoot 学习

什么是 SpringBoot SpringBoot 是基于 Spring 生态的开源框架&#xff0c;旨在简化 Spring 应用的初始化搭建和开发配置。它通过约定大于配置的理念&#xff0c;提供快速构建生产级应用的解决方案&#xff0c;显著降低开发者对 XML 配置和依赖管理的负担。 特点&#xff1a; …...

MoE架构解析:如何用“分治”思想打造高效大模型?

在人工智能领域&#xff0c;模型规模的扩大似乎永无止境。从GPT-3的1750亿参数到传闻中的GPT-4万亿级规模&#xff0c;每一次突破都伴随着惊人的算力消耗。但当我们为这些成就欢呼时&#xff0c;一个根本性问题愈发尖锐&#xff1a;如何在提升模型能力的同时控制计算成本&#…...

云服务器和独立服务器的区别在哪

在当今数字化的时代&#xff0c;服务器成为了支撑各种业务和应用的重要基石。而在服务器的领域中&#xff0c;云服务器和独立服务器是两个备受关注的选项。那么&#xff0c;它们到底有何区别呢&#xff1f; 首先&#xff0c;让我们来聊聊成本。云服务器通常采用按需付费的模式…...

使用 Pandas 进行多格式数据整合:从 Excel、JSON 到 HTML 的处理实战

前言 在数据处理与分析的实际场景中&#xff0c;我们经常需要整合不同格式的数据&#xff0c;例如 Excel 表格、JSON 配置文件、HTML 报表等。本文以一个具体任务&#xff08;蓝桥杯模拟练习题&#xff09;为例&#xff0c;详细讲解如何使用 Python 的 Pandas 库结合其他工具&…...

深入解析 Linux 中动静态库的加载机制:从原理到实践

引言 在 Linux 开发中&#xff0c;动静态库是代码复用的核心工具。静态库&#xff08;.a&#xff09;和动态库&#xff08;.so&#xff09;的加载方式差异显著&#xff0c;直接影响程序的性能、灵活性和维护性。本文将深入剖析两者的加载机制&#xff0c;结合实例演示和底层原…...

VuePress 使用教程:从入门到精通

VuePress 使用教程&#xff1a;从入门到精通 VuePress 是一个以 Vue 驱动的静态网站生成器&#xff0c;它为技术文档和技术博客的编写提供了优雅而高效的解决方案。无论你是个人开发者、团队负责人还是开源项目维护者&#xff0c;VuePress 都能帮助你轻松地创建和管理你的文档…...

Kafka与Spark-Streaming

大数据处理的得力助手&#xff1a;Kafka与Spark-Streaming 在大数据处理的领域中&#xff0c;Kafka和Spark-Streaming都是极为重要的工具。今天&#xff0c;咱们就来深入了解一下它们&#xff0c;看看这些技术是如何让数据处理变得高效又强大的。先来说说Kafka&#xff0c;它是…...

【设计】接口幂等性设计

1. 幂等性定义 接口幂等性&#xff1a; 无论调用次数多少&#xff0c;对系统状态的影响与单次调用相同。 比如用户支付接口因网络延迟重复提交了三次。 导致原因&#xff1a; 用户不可靠&#xff08;手抖多点&#xff09;网络不可靠&#xff08;超时重传&#xff09;系统不可…...

闲聊人工智能对媒体的影响

技术总是不断地改变信息的传播方式。互联网促进了社交媒体的蓬勃发展。 网络媒体成为主流。大语言模型为代表的人工智能的出现&#xff0c;又会对媒体传播带来怎样的改变呢&#xff1f;媒体的演变反映了社会和技术的演变。 人工智能(AI) 将继续对整个媒体行业产生变革性的影响。…...

卷积神经网络--手写数字识别

本文我们通过搭建卷积神经网络模型&#xff0c;实现手写数字识别。 pytorch中提供了手写数字的数据集 &#xff0c;我们可以直接从pytorch中下载 MNIST中包含70000张手写数字图像&#xff1a;60000张用于训练&#xff0c;10000张用于测试 图像是灰度的&#xff0c;28x28像素 …...

Pandas 数据导出:如何将 DataFrame 追加到 Excel 的不同工作表

在数据分析和数据处理过程中&#xff0c;将数据导出到 Excel 文件是一个常见的需求。Pandas 提供了强大的功能来实现这一需求&#xff0c;尤其是将数据追加到同一个 Excel 文件的不同工作表&#xff08;Sheet&#xff09;中。本文将详细介绍如何使用 Pandas 实现这一功能&#…...

Unity中数据和资源加密(异或加密,AES加密,MD5加密)

在项目开发中&#xff0c;始终会涉及到的一个问题&#xff0c;就是信息安全&#xff0c;在调用接口&#xff0c;或者加载的资源&#xff0c;都会涉及安全问题&#xff0c;因此就出现了各种各样的加密方式。 常见的也是目前用的最广的加密方式&#xff0c;分别是&#xff1a;DE…...

SQL Server 2019 安装与配置详细教程

一、写在最前的心里话 和 MySQL 对比&#xff0c;SQL Server 的安装和使用确实要处理很多细节&#xff1a; 需要选择配置项很多有“定义实例”的概念&#xff0c;同一机器可以运行多个数据库服务设置身份验证方式时&#xff0c;需要同时配置 Windows 和 SQL 登录要想 Spring …...

Qt 调试信息重定向到本地文件

1、在Qt软件开发过程中&#xff0c;我们经常使用qDebug()输出一些调试信息在QtCreator终端上。 但若将软件编译、生成、打包为一个完整的可运行的程序并安装在系统中后&#xff0c;系统中没有QtCreator和编译环境&#xff0c;那应用程序出现问题&#xff0c;如何输出信息排查…...

MyBatisPlus文档

一、MyBatis框架回顾 使用springboot整合Mybatis,实现Mybatis框架的搭建 1、创建示例项目 (1)、创建工程 新建工程 创建空工程 创建模块 创建springboot模块 选择SpringBoot版本 (2)、引入依赖 <dependencies><dependency><groupId>org.springframework.…...

Memcached 主主复制架构搭建与 Keepalived 高可用实现

实验目的 掌握基于 repcached 的 Memcached 主主复制配置 实现通过 Keepalived 的 VIP 高可用机制 验证数据双向同步及故障自动切换能力 实验环境 角色IP 地址主机名虚拟 IP (VIP)主节点10.1.1.78server-a10.1.1.80备节点10.1.1.79server-b10.1.1.80 操作系统: CentOS 7 软…...

Android 使用支付接口,需要进行的加密逻辑:MD5、HMAC-SHA256以及RSA

目录 前言MD5HMAC-SHA256RSA其他 前言 不使用加密​​&#xff1a;支付系统如同「裸奔」&#xff0c;面临数据泄露、资金被盗、法律追责等风险。 正确使用加密​​&#xff1a;构建「端到端安全防线」&#xff0c;确保交易合法可信&#xff0c;同时满足国际合规要求。 支付系…...

软件工程效率优化:一个分层解耦与熵减驱动的系统框架

软件工程效率优化&#xff1a;一个分层解耦与熵减驱动的系统框架** 摘要 (Abstract) 本报告构建了一个全面、深入、分层的软件工程效率优化框架&#xff0c;旨在超越简单的技术罗列&#xff0c;从根本的价值驱动和熵减原理出发&#xff0c;系统性地探讨提升效率的策略与实践。…...

鸿蒙ArkUI之相对布局容器(RelativeContainer)实战之狼人杀布局,详细介绍相对布局容器的用法,附上代码,以及效果图

在鸿蒙应用开发中&#xff0c;若是遇到布局相对复杂的场景&#xff0c;往往需要嵌套许多层组件&#xff0c;去还原UI图的效果&#xff0c;若是能够掌握相对布局容器的使用&#xff0c;对于复杂的布局场景&#xff0c;可直接减少组件嵌套&#xff0c;且随心所欲完成复杂场景的布…...

详解 Servlet 处理表单数据

Servlet 处理表单数据 1. 什么是 Servlet&#xff1f;2. 表单数据如何发送到 Servlet&#xff1f;2.1 GET 方法2.2 POST 方法 3. Servlet 如何接收表单数据&#xff1f;3.1 获取单个参数&#xff1a;getParameter()示例&#xff1a; 3.2 获取多个参数&#xff1a;getParameterV…...

Spring Cloud Gateway 如何将请求分发到各个服务

前言 在微服务架构中&#xff0c;API 网关&#xff08;API Gateway&#xff09;扮演着非常重要的角色。它负责接收客户端请求&#xff0c;并根据预定义的规则将请求路由到对应的后端服务。Spring Cloud Gateway 是 Spring 官方推出的一款高性能网关&#xff0c;支持动态路由、…...

解释器体系结构风格-笔记

解释器&#xff08;Interpreter&#xff09;是一种软件设计模式或体系结构风格&#xff0c;主要用于为语言&#xff08;或表达式&#xff09;定义其语法、语义&#xff0c;并通过解释器来解析和执行语言中的表达式。解释器体系结构风格广泛应用于编程语言、脚本语言、规则引擎、…...

线程函数库

pthread_create函数 pthread_create 是 POSIX 线程库&#xff08;pthread&#xff09;中的一个函数&#xff0c;用于创建一个新的线程。 头文件 #include <pthread.h> 函数原型 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*s…...

[C]基础13.深入理解指针(5)

博客主页&#xff1a;向不悔本篇专栏&#xff1a;[C]您的支持&#xff0c;是我的创作动力。 文章目录 0、总结1、sizeof和strlen的对比1.1 sizeof1.2 strlen1.3 sizeof和strlen的对比 2、数组和指针笔试题解析2.1 一维数组2.2 字符数组2.2.1 代码12.2.2 代码22.2.3 代码32.2.4 …...