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

news2025/4/26 18:37:07

一. 简介

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

什么是哈希表-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) 向哈希表中插入新的键值对

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

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

相关文章

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, …

SpringBoot 学习

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

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

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

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

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

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

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

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 软…

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

在鸿蒙应用开发中&#xff0c;若是遇到布局相对复杂的场景&#xff0c;往往需要嵌套许多层组件&#xff0c;去还原UI图的效果&#xff0c;若是能够掌握相对布局容器的使用&#xff0c;对于复杂的布局场景&#xff0c;可直接减少组件嵌套&#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 …

OpenCV 图形API(60)颜色空间转换-----将图像从 YUV 色彩空间转换为 RGB 色彩空间函数YUV2RGB()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像从 YUV 色彩空间转换为 RGB。 该函数将输入图像从 YUV 色彩空间转换为 RGB。Y、U 和 V 通道值的常规范围是 0 到 255。 输出图像必须是 8…

hbuilderx云打包生成的ipa文件如何上架

使用hbuilderx打包&#xff0c;会遇到一个问题。开发的ios应用&#xff0c;需要上架到app store&#xff0c;因此&#xff0c;就需要APP store的签名证书&#xff0c;并且还需要一个像xcode那样的工具来上架app store。 我们这篇文章说明下&#xff0c;如何在windows电脑&…

Golang | 位运算

位运算比常规运算快&#xff0c;常用于搜索引擎的筛选功能。例如&#xff0c;数字除以二等价于向右移位&#xff0c;位移运算比除法快。

产品动态|千眼狼sCMOS科学相机捕获单分子荧光信号

单分子荧光成像技术&#xff0c;作为生物分子动态研究的关键工具&#xff0c;对捕捉微弱信号要求严苛。传统EMCCD相机因成本高昂&#xff0c;动态范围有限&#xff0c;满阱容量低等问题&#xff0c;制约单分子研究成果产出效率。 千眼狼精准把握科研需求与趋势&#xff0c;自研…

Hot100方法及易错点总结2

本文旨在记录做hot100时遇到的问题及易错点 五、234.回文链表141.环形链表 六、142. 环形链表II21.合并两个有序链表2.两数相加19.删除链表的倒数第n个节点 七、24.两两交换链表中的节点25.K个一组翻转链表(坑点很多&#xff0c;必须多做几遍)138.随机链表的复制148.排序链表 N…

网络:手写HTTP

目录 一、HTTP是应用层协议 二、HTTP服务器 三、HTTP服务 认识请求中的uri HTTP支持默认首页 响应 功能完善 套接字复用 一、HTTP是应用层协议 HTTP下层是TCP协议&#xff0c;站在TCP的角度看&#xff0c;要提供的服务是HTTP服务。 这是在原来实现网络版计算器时&am…

【计算机视觉】CV实战项目 - 基于YOLOv5的人脸检测与关键点定位系统深度解析

基于YOLOv5的人脸检测与关键点定位系统深度解析 1. 技术背景与项目意义传统方案的局限性YOLOv5多任务方案的优势 2. 核心算法原理网络架构改进关键点回归分支损失函数设计 3. 实战指南&#xff1a;从环境搭建到模型应用环境配置数据准备数据格式要求数据目录结构 模型训练配置文…

【python】如何将python程序封装为cpython的库

python程序在发布时&#xff0c;往往会打包为cpython的库&#xff0c;并且根据应用服务器的不同架构&#xff08;x86/aarch64&#xff09;&#xff0c;以及python的不同版本&#xff0c;封装的输出类型也是非常多。本文介绍不同架构指定python下的代码打包方式&#xff1a; 首…

计算机组成原理 课后练习

例一&#xff1a; 例二&#xff1a; 1. 原码一位乘 基本原理 原码是一种直接表示数值符号和大小的方式&#xff1a;最高位为符号位&#xff08;0表示正&#xff0c;1表示负&#xff09;&#xff0c;其余位表示数值的绝对值。原码一位乘的核心思想是逐位相乘&#xff0c;并通…