源代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 键值对节点
typedef struct Node {char* key;int value;struct Node* next;
} Node;// Map结构
typedef struct {Node* buckets[100];  // 固定大小的哈希桶(简化版)int size;            // 元素数量
} Map;// 简单哈希函数(字符串转索引)
int hash(const char* key) {int hash = 0;while (*key) {hash += (*key++);}return hash % 100;  // 对应buckets大小
}// 初始化Map
void initMap(Map* map) {memset(map->buckets, 0, sizeof(map->buckets));map->size = 0;
}// 插入或更新键值对
void put(Map* map, const char* key, int value) {if (!key) return;int index = hash(key);Node* curr = map->buckets[index];// 查找是否已存在键while (curr) {if (strcmp(curr->key, key) == 0) {curr->value = value;  // 更新值return;}curr = curr->next;}// 不存在则创建新节点(头插法)Node* newNode = (Node*)malloc(sizeof(Node));if (!newNode) return;newNode->key = strdup(key);if (!newNode->key) {free(newNode);return;}newNode->value = value;newNode->next = map->buckets[index];map->buckets[index] = newNode;map->size++;
}// 根据键获取值
int get(Map* map, const char* key, int* result) {if (!key || !result) return 0;int index = hash(key);Node* curr = map->buckets[index];while (curr) {if (strcmp(curr->key, key) == 0) {*result = curr->value;return 1;  // 找到}curr = curr->next;}return 0;  // 未找到
}// 删除键值对
int removeKey(Map* map, const char* key) {if (!key) return 0;int index = hash(key);Node* curr = map->buckets[index];Node* prev = NULL;while (curr) {if (strcmp(curr->key, key) == 0) {if (prev) {prev->next = curr->next;} else {map->buckets[index] = curr->next;}free(curr->key);free(curr);map->size--;return 1;}prev = curr;curr = curr->next;}return 0;
}// 获取元素数量
int size(Map* map) {return map->size;
}// 清空Map
void clear(Map* map) {for (int i = 0; i < 100; i++) {Node* curr = map->buckets[i];while (curr) {Node* next = curr->next;free(curr->key);free(curr);curr = next;}map->buckets[i] = NULL;}map->size = 0;
}// 测试函数
int main() {Map map;initMap(&map);// 插入数据put(&map, "apple", 10);put(&map, "banana", 5);put(&map, "orange", 8);// 获取数据int val;if (get(&map, "banana", &val)) {printf("banana: %d\n", val);  // 输出:banana: 5}// 更新数据put(&map, "banana", 15);get(&map, "banana", &val);printf("updated banana: %d\n", val);  // 输出:updated banana: 15// 删除数据removeKey(&map, "orange");printf("size after remove: %d\n", size(&map));  // 输出:size after remove: 2// 清空Mapclear(&map);printf("final size: %d\n", size(&map));  // 输出:final size: 0return 0;
}

代码详解: 

这个代码实现了一个简单的 哈希表(Hash Map) 数据结构,用于存储键值对(key-value pairs)。下面将详细解释代码的每一部分及其功能:


1. 数据结构设计

节点结构 Node
typedef struct Node {char* key;          // 字符串键int value;          // 整数值struct Node* next;  // 指向下一个节点的指针(处理哈希冲突)
} Node;
  • 作用:存储键值对的基本单元

  • 关键点

    • key 使用 strdup 动态分配内存存储字符串

    • next 指针用于解决哈希冲突(链地址法)

哈希表结构 Map
typedef struct {Node* buckets[100];  // 哈希桶数组(固定大小100)int size;            // 当前存储的元素数量
} Map;
  • 作用:管理整个哈希表

  • 关键点

    • buckets 是长度为 100 的指针数组,每个桶对应一个链表

    • size 记录当前存储的键值对数量


2. 核心功能实现

哈希函数 hash()
int hash(const char* key) {int hash = 0;while (*key) {hash += (*key++);  // 简单累加ASCII值}return hash % 100;     // 映射到0-99的桶索引
}
  • 作用:将任意字符串键映射到固定范围的索引

  • 特点

    • 简单但容易产生冲突(如 "ab" 和 "ba" 哈希值相同)

    • 使用取模运算确保结果在桶数组范围内

初始化函数 initMap()
void initMap(Map* map) {memset(map->buckets, 0, sizeof(map->buckets));map->size = 0;
}
  • 作用:初始化哈希表状态

  • 关键操作

    • 将所有桶指针设为 NULL

    • 元素计数器 size 归零

插入/更新函数 put()
void put(Map* map, const char* key, int value) {// 1. 计算哈希索引int index = hash(key);// 2. 检查键是否已存在(更新值)Node* curr = map->buckets[index];while (curr) {if (strcmp(curr->key, key) == 0) {curr->value = value;return;}curr = curr->next;}// 3. 创建新节点(头插法)Node* newNode = malloc(sizeof(Node));newNode->key = strdup(key);  // 复制键字符串newNode->value = value;newNode->next = map->buckets[index];map->buckets[index] = newNode;map->size++;
}
  • 特点

    • 键存在时更新值

    • 键不存在时使用头插法添加新节点

    • 使用 strdup 深拷贝键字符串

查找函数 get()
int get(Map* map, const char* key, int* result) {int index = hash(key);Node* curr = map->buckets[index];while (curr) {if (strcmp(curr->key, key) == 0) {*result = curr->value;  // 通过指针返回结果return 1;  // 成功找到}curr = curr->next;}return 0;  // 未找到
}
  • 特点

    • 返回查找状态(1成功/0失败)

    • 通过指针参数 result 返回查找到的值

删除函数 removeKey()
int removeKey(Map* map, const char* key) {int index = hash(key);Node* curr = map->buckets[index];Node* prev = NULL;while (curr) {if (strcmp(curr->key, key) == 0) {// 从链表中删除节点if (prev) prev->next = curr->next;else map->buckets[index] = curr->next;// 释放内存free(curr->key);free(curr);map->size--;return 1;  // 删除成功}prev = curr;curr = curr->next;}return 0;  // 键不存在
}
  • 关键操作

    • 处理链表中间/头部节点的删除

    • 释放键字符串和节点本身的内存

辅助函数
int size(Map* map) { return map->size; }  // 返回元素数量void clear(Map* map) {                   // 清空整个哈希表for (int i = 0; i < 100; i++) {Node* curr = map->buckets[i];while (curr) {Node* next = curr->next;free(curr->key);free(curr);curr = next;}map->buckets[i] = NULL;}map->size = 0;
}

3. 测试逻辑(main函数)

int main() {Map map;initMap(&map);  // 初始化// 插入测试put(&map, "apple", 10);put(&map, "banana", 5);put(&map, "orange", 8);// 查找测试int val;get(&map, "banana", &val);  // 输出: banana: 5// 更新测试put(&map, "banana", 15);    // 更新值get(&map, "banana", &val);  // 输出: updated banana: 15// 删除测试removeKey(&map, "orange");printf("size after remove: %d\n", size(&map));  // 输出: 2// 清空测试clear(&map);printf("final size: %d\n", size(&map));  // 输出: 0return 0;
}

4. 代码功能总结

  1. 核心数据结构

    • 实现了一个基于链地址法的哈希表

    • 支持字符串键(key)和整数值(value)的存储

  2. 支持操作

    • put(): 插入/更新键值对

    • get(): 查找键对应的值

    • removeKey(): 删除指定键

    • size(): 获取元素数量

    • clear(): 清空整个哈希表

  3. 冲突解决

    • 使用链表解决哈希冲突(链地址法)

    • 每个桶是一个链表头节点

  4. 内存管理

    • 动态分配节点内存

    • 使用 strdup 复制键字符串

    • 删除/清空时释放所有内存


5. 局限性及改进建议

  1. 固定桶大小

    • 桶数组固定为100,可能导致冲突率高

    • 改进:实现动态扩容(如负载因子>0.75时扩容)

  2. 简单哈希函数

    • 当前哈希函数易产生冲突

    • 改进:使用更复杂的哈希算法(如djb2)

  3. 键类型限制

    • 仅支持字符串键

    • 改进:使用泛型支持多种键类型

  4. 线程安全

    • 非线程安全

    • 改进:添加互斥锁实现线程安全

  5. 错误处理

    • 未处理内存分配失败情况

    • 改进:添加NULL指针检查


6. 实际应用场景

  1. 配置存储:存储程序配置参数(键值对)

  2. 缓存系统:实现简单的内存缓存

  3. 词频统计:统计文本中单词出现次数

  4. 符号表:编译器中的变量管理

  5. 路由表:网络设备中的IP路由查找

注:该代码是本人自己所写,可能不够好,不够简便,欢迎大家指出我的不足之处。如果遇见看不懂的地方,可以在评论区打出来,进行讨论,或者联系我。上述内容全是我自己理解的,如果你有别的想法,或者认为我的理解不对,欢迎指出!!!如果可以,可以点一个免费的赞支持一下吗?谢谢各位彦祖亦菲!!!!!

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

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

相关文章

Logback示例解析

<configuration><!-- 环境变量 --><springProperty scope"context" name"app.name" source"spring.application.name" defaultValue"application"/><!-- 日志存放路径 --><property name"log.path&qu…

elementui响应式数据类型变更情况

背景。vue2。data中定义的响应数据类型是[]数组。应用在el-select中&#xff08;非multiple情况&#xff09;。当发生响应数据有变更渲染视图时&#xff0c;发现定义的数组转换成了字符串。 本身不是问题。但因为疏忽引发了watch监听formData数据时产生了产生了多次监听事件。…

人机融合智能 | 人智交互语境下的设计新模态

本章旨在探讨技术与设计领域在人智交互语境下的关系及其影响,讨论通过传统设计对人智交互的优化方法。通过回顾大数据和发展趋势,以 AI技术作为重要的技术推力,我们认为 AI技术将会在未来成为设计领域不可缺少的重要环节,并能够帮助设计师更加高效、准确地开展设计工作。本章着…

C++设计模式分类(GOF-23种设计模式)

文章目录 GOF-23 设计模式分类一、从目的分类1. 创建型&#xff08;Creational&#xff09;模式2. 结构型&#xff08;Structural&#xff09;模式3. 行为型&#xff08;Behavioral&#xff09;模式 二、从范围分类1. 类模式&#xff08;Class Pattern&#xff09;2. 对象模式&…

AbMole| LY294002(M1925)

LY294002是一种广谱的PI3K抑制剂&#xff0c;对PI3Kα/δ/β的IC50分别为0.5 μM/0.57 μM/0.97 μM。LY294002 也可以抑制 CK2 的活性&#xff0c;IC50 为 98 nM。LY294002 还是一种竞争性 DNA-PK 抑制剂&#xff0c;可逆结合 DNA-PK 的激酶结构域&#xff0c;IC50 为 1.4 μM…

第1章,[标签 Win32] :第一个 WIn32 程序,MessageBox 函数

专栏导航 上一篇&#xff1a;第1章&#xff0c;[标签 Win32] &#xff1a;第一个 WIn32 程序&#xff0c;程序入口 回到目录 下一篇&#xff1a;无 本节前言 本节的学习&#xff0c;需要前两节的内容作为先修知识。如果还没有去看本专栏的前两节&#xff0c;请你先去学习它…

求助帖:学Java开发方向还是网络安全方向前景好

最近网络安全被一个培训机构吹得天花乱坠&#xff0c;虽然他家既有网安又有java和UI&#xff0c;我也是学软件工程的&#xff08;山西某211&#xff0c;此机构是每年和我们学校合作的校企公司&#xff09;&#xff0c;但那里的老师仍然大力推荐我学网络安全&#xff08;渗透、代…

OpenCV 图像仿射变换之旋转

一、知识点 1、void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags INTER_LINEAR, int borderMode BORDER_CONSTANT, …

HCIP-数据通信基础

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 本篇笔记是根据B站上的视频教程整理而成&#xff0c;感谢UP主的精彩讲解&#xff01;如果需要了解更多细节&#xff0c;可以参考以下视频&#xff1a;…

C语言基本数据类型与变量详解

# C语言基本数据类型与变量详解 ## 数据类型概述 在C语言中&#xff0c;数据类型决定了变量在内存中的存储方式和大小&#xff0c;以及可以对其执行的操作。合理选择数据类型能够提高程序的效率和准确性&#xff0c;避免内存浪费和数据溢出等问题。 C语言的基本数据类型主要包括…

Babylon.js学习之路《十、高级几何体:自定义模型与复杂形状生成》

文章目录 1. 引言&#xff1a;高级几何体的应用场景2. 参数化建模&#xff1a;Babylon.MeshBuilder2.1 扩展几何体类型2.2 自定义多边形&#xff08;ExtrudePolygon&#xff09; 3. 顶点级建模&#xff1a;自定义VertexData3.1 手动定义顶点数据3.2 动态生成地形&#xff08;高…

【赵渝强老师】Kubernetes的安全框架

Kubernetes集群的安全框架主要由以下认证、鉴权和准入控制三个阶段组成。这三个阶段的关系如下图所示。 视频讲解如下 【赵渝强老师】Kubernetes的安全框架 认证&#xff08;Authentication&#xff09; 当客户端与Kubernetes集群建立HTTP通信时&#xff0c;首先HTTP请求会进…

CDN与静态资源优化

CDN与静态资源优化 在现代Web系统和AI应用中&#xff0c;随着用户访问量的不断攀升&#xff0c;静态资源&#xff08;如HTML、CSS、JavaScript、图片、音视频、模型文件等&#xff09;带来的负载日益沉重。尤其在大模型推理、前端渲染、广告投放等场景中&#xff0c;静态资源的…

如何填写“appium inspector”内容?

1. 确认已经开启appium的服务&#xff0c;运行appium 参考内容&#xff1a;{"appium:platformName": "Android", # 系统名称"appium:platformVersion": "9", # 安卓版本&#xff0c;看设备"appium:deviceName": "3d…

mysql server层做了什么

服务器处理客户端请求 服务器程序在处理来自客户端的查询请求时&#xff0c;大致需要分为3部分&#xff1a;连接管理、解析与优化、存储引擎。 连接管理 每当有一个客户端进程连接到服务器进程时&#xff0c;服务器进程都会创建一个线程专门处理与这个客户端的交互&#xff…

APISIX 简介:云原生 API 网关的架构与实践

文章目录 引言&#xff1a;APISIX 概述基于Nginx构建的原因基于etcd构建的原因 架构图示架构分层解析管理层&#xff1a;人机交互与配置入口控制层&#xff1a;配置管理与集群协调数据面&#xff1a;请求处理与流量转发说明&#xff1a;关于OpenRestry 引言&#xff1a;APISIX …

【AI作画】第3章 LORA加载器

目录 LORA加载器 管道信息 ​编辑 ​编辑 ​编辑 lora模型的串接 作品集 LORA加载器 前面我们已经分析过节点目录了&#xff0c;现在我们来看一下LORA加载器。我们进行图片渲染&#xff0c;一般都需要LORA模型的。 首先&#xff0c;我们“鼠标右键——添加节点——…

Xilinx XC7A12T‑1CPG238I Artix‑7 FPGA

XC7A12T‑1CPG238I 以其独特的性能与封装组合&#xff0c;成为诸多工程师的首选方案。下面&#xff0c;我们从多个维度对这款芯片做深入剖析。 一、产品定位与封装特点 XC7A12T‑1CPG238I 属于赛灵思&#xff08;Xilinx&#xff09;28 nm Artix‑7 系列中的入门级型号&#x…

如何利用 Java 爬虫获得微店商品详情:实战指南

在电商领域&#xff0c;微店作为众多商家的线上销售渠道之一&#xff0c;其商品详情数据对于市场分析、竞品研究和商业决策具有重要价值。Java 爬虫技术可以帮助我们高效地获取这些数据。本文将详细介绍如何使用 Java 编写爬虫&#xff0c;获取微店商品详情。 一、准备工作 &…

【Bug】MAUI自定义弹窗在IOS有异常背景

文章目录 问题问题代码原因解决处理Bug的具体步骤 问题 自定义弹窗有异常背景 问题代码 <mct:Popup xmlns"http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x"http://schemas.microsoft.com/winfx/2009/xaml"xmlns:converters"clr-names…