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

Hash哈希表以及代码

哈希表(Hash Table),也叫散列表,是一种用于存储键值对(key-value pairs)的高效数据结构。它通过一个哈希函数(Hash Function)将任意的键(如字符串、数字等)映射到一个固定范围的索引(通常是一个数组下标),进而实现数据的快速插入、查找、删除和修改。

哈希表在平均情况下,这些操作的时间复杂度可以达到:

插入:O(1)

查找:O(1)

删除:O(1)

修改:O(1)

但在极端情况下(例如大量哈希冲突且未有效处理),性能可能退化至O(n)

哈希表的核心在于:

  1. 哈希函数:将任意 key 映射为数组的一个索引,决定该键值对应该存放在哪个“桶(bucket)”中。
  2. 冲突解决:由于不同的 key 可能映射到同一个索引(即哈希冲突),因此需要有机制来处理多个键值对共享同一个桶的情况。

这里使用的是链地址法解决哈希冲突。本代码只使用了简单的线性链表。

链地址法:在每个数组位置(桶)上维护一个链表(或树结构)。当发生冲突时,将新元素添加到对应索引的链表中。如果冲突链表过长,这个时候可以将这个链表转换为红黑树、最小堆。由原来链表时间复杂度O(n) 转换为红黑树时间复杂度O(log n) ;

本文采用一种简单的字符累加取模法作为哈希函数:

static int _hash(char *key, int size) { if (!key) return -1; int sum = 0; int i = 0; while (key[i] != 0) { sum += key[i]; // 累加每个字符的 ASCII 值 i++; } return sum % size; // 取模得到桶的索引 }

对于存储节点的定义如下:

typedef struct hashnode_s{ char *key; char *value; struct hashnode_s *next; } hashnode_t;

一对 键值对 以及 next节点.

分别实现了初始化函数,申请节点函数,销毁函数,增删改函数。

核心 API:

init_hashtable初始化

_create_node创建节点

_hash哈希函数

hashtable_insert插入

get_hashtable查找

hashtable_delete删除

hashtable_modify修改

count_hashtable查询节点数量

dest_hashtable销毁

测试 main() 函数:涵盖初始化 → 插入 → 查询 → 统计 → 删除 → 修改 的完整流程

完整代码:

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <pthread.h> #define MAX_KEY_LEN 128 #define MAX_VALUE_LEN 512 #define MAX_TABLE_SIZE 1024 typedef struct hashnode_s{ char *key; char *value; struct hashnode_s *next; } hashnode_t; typedef struct hashtable_s{ hashnode_t **nodes; int node_count; } hashtable_t; hashtable_t Hash; // 哈希函数 static int _hash(char *key, int size) { if(!key) return -1; int sum = 0; int i = 0; while(key[i]!=0){ sum += key[i]; i++; } return sum % size; } hashnode_t *_create_node(char *key, char *value){ hashnode_t *node = (hashnode_t *)malloc(sizeof(hashnode_t)); if(!node) return NULL; node->key = (char *)malloc(strlen(key) + 1); if (!node->key){ free(node); return NULL; } strcpy(node->key, key); node->value = (char *)malloc(strlen(value) + 1); if(!node->value){ free(node->key); free(node); return NULL; } strcpy(node->value, value); node->next = NULL; return node; } int init_hashtable(hashtable_t *hash){ if(!hash) return -1; hash->nodes = (hashnode_t **)malloc(sizeof(hashnode_t *) * MAX_TABLE_SIZE); hash->node_count = 0; return 0; } int dest_hashtable(hashtable_t *hash){ if(!hash) return -1; int i = 0; for (i = 0; i < hash->node_count; i++){ hashnode_t *node = hash->nodes[i]; while(node != NULL){ hashnode_t *tmp = node; node = node->next; hash->nodes[i] = node;//为什么?没有这行代码也可以吧 if (tmp->key) free(tmp->key); if(tmp->value) free(tmp->value); free(tmp); } } free(hash->nodes); return 0; } int hashtable_insert(hashtable_t *hash, char *key, char *value) { if(!hash || !key || !value) return -1; int idx = _hash(key, MAX_TABLE_SIZE); hashnode_t *node = hash->nodes[idx]; while(node != NULL){ if(strcmp(node->key,key) == 0) return 1; // 已经存在这个key node = node->next; } hashnode_t *new_node = _create_node(key, value); // 头插法 new_node->next = hash->nodes[idx]; hash->nodes[idx] = new_node; hash->node_count++; return 0; } char *get_hashtable(hashtable_t *hash, char *key){ if(!hash || !key ) return NULL; int idx = _hash(key, MAX_TABLE_SIZE); hashnode_t *node = hash->nodes[idx]; while(node != NULL){ if(strcmp(node->key,key) == 0) return node->value; node = node->next; } return NULL;// 没找到key } int count_hashtable(hashtable_t *hash){ return hash->node_count; } int hashtable_delete(hashtable_t *hash, char *key) { if(!hash || !key ) return -1; hashnode_t *node_del_per = NULL; hashnode_t *node_del = NULL; int idx = _hash(key, MAX_TABLE_SIZE); hashnode_t *node = hash->nodes[idx]; if (node == NULL) { return -1; // 没有找到任何节点 } if(strcmp(node->key,key) == 0){// 排查第一个元素 node_del = node; hash->nodes[idx] = node_del->next; node_del->next = NULL; if (node_del->key) free(node_del->key); if(node_del->value) free(node_del->value); free(node_del); hash->node_count--; return 0; } while (node->next != NULL)// 排查其他元素 { if(strcmp(node->next->key,key) == 0){ node_del_per = node; node_del = node->next; node_del_per->next = node_del->next; node_del->next = NULL; if (node_del->key) free(node_del->key); if(node_del->value) free(node_del->value); free(node_del); hash->node_count--; return 0; } node = node->next; } return 1;// 没找到 } int hashtable_modify(hashtable_t *hash, char *key, char *value) { if(!hash || !key || !value) return -1; int idx = _hash(key, MAX_TABLE_SIZE); hashnode_t *node = hash->nodes[idx]; while(node != NULL){ if(strcmp(node->key,key) == 0) break; node = node->next; } if(node == NULL)//没找到key { return 1; } if(node->value) free(node->value); node->value = (char *)malloc(strlen(value) + 1); if(!node->value){ free(node->key); free(node); return -1; } strcpy(node->value, value); return 0; } // 测试部分ai写的 int main(void) { int i = -100; // ---------------------------------------- // 1. Initialize hashtable // ---------------------------------------- printf("1. Initialize hashtable\n"); i = init_hashtable(&Hash); if (i == 0) printf(" Hash table initialized successfully\n"); else printf(" Hash table initialization failed, return value: %d\n", i); printf("\n"); // ---------------------------------------- // 2. Insert key-value pairs // ---------------------------------------- printf("2. Insert key-value pairs\n"); i = hashtable_insert(&Hash, "King", "111"); if (i == 0) printf(" Inserted King=111: success\n"); else if (i == 1) printf(" Inserted King=111: failed, key already exists\n"); else printf(" Inserted King=111: failed, error code: %d\n", i); i = hashtable_insert(&Hash, "Aing", "222"); if (i == 0) printf(" Inserted Aing=222: success\n"); else if (i == 1) printf(" Inserted Aing=222: failed, key already exists\n"); else printf(" Inserted Aing=222: failed, error code: %d\n", i); i = hashtable_insert(&Hash, "Bing", "333"); if (i == 0) printf(" Inserted Bing=333: success\n"); else if (i == 1) printf(" Inserted Bing=333: failed, key already exists\n"); else printf(" Inserted Bing=333: failed, error code: %d\n", i); printf("\n"); // ---------------------------------------- // 3. Get key values // ---------------------------------------- printf("3. Get key values\n"); char *str = get_hashtable(&Hash, "King"); if (str) printf(" Get King: success, value = %s\n", str); else printf(" Get King: failed, key not found\n"); str = get_hashtable(&Hash, "Aing"); if (str) printf(" Get Aing: success, value = %s\n", str); else printf(" Get Aing: failed, key not found\n"); str = get_hashtable(&Hash, "Cing"); if (str) printf(" Get Cing: success, value = %s\n", str); else printf(" Get Cing: failed, key not found\n"); printf("\n"); // ---------------------------------------- // 4. Count entries // ---------------------------------------- printf("4. Count entries\n"); int count = count_hashtable(&Hash); printf(" Total entries in hash table: %d\n", count); printf("\n"); // ---------------------------------------- // 5. Delete a key // ---------------------------------------- printf("5. Delete a key\n"); i = hashtable_delete(&Hash, "King"); if (i == 0) { printf(" Delete King: success\n"); } else { printf(" Delete King: failed, key not found\n"); } count = count_hashtable(&Hash); printf(" Total entries after deletion: %d\n", count); printf("\n"); str = get_hashtable(&Hash, "King"); if (str) printf(" Verify deletion: King still exists, value = %s\n", str); else printf(" Verify deletion: King no longer exists\n"); printf("\n"); // ---------------------------------------- // 6. Modify a key // ---------------------------------------- printf("6. Modify a key\n"); i = hashtable_modify(&Hash, "Aing", "999"); if (i == 0) printf(" Modify Aing=999: success\n"); else printf(" Modify Aing=999: failed, key not found\n"); str = get_hashtable(&Hash, "Aing"); if (str) printf(" Get modified Aing: value = %s\n", str); else printf(" Get modified Aing: failed, key not found\n"); printf("\n"); count = count_hashtable(&Hash); printf(" Total entries after modification: %d\n", count); printf("\n"); // ---------------------------------------- // 7. End // ---------------------------------------- // Free memory dest_hashtable(&Hash); return 0; }
http://www.jsqmd.com/news/453515/

相关文章:

  • 雷达原理(第三版) 丁鹭飞 中最主要的公式
  • Flutter SVG图片Demo
  • 编译器优化屏障使用
  • 基于SpringBoot+Vue的船舶监造系统管理系统设计与实现【Java+MySQL+MyBatis完整源码】
  • 【ArcGIS技巧】表格批量转图片(emf格式)方便相对路径索引表格
  • Qwen3-ASR-0.6B语音识别实测:轻量级模型,专业级效果,小白也能用
  • redis具体情况介绍
  • 云容笔谈微信小程序前端开发实战:打造个人AI画师工具
  • HeyGem数字人视频生成系统批量版:5分钟快速部署,新手也能轻松上手
  • L1-020 帅到没朋友(分数20)
  • 索引和事务
  • 一键部署梦幻动漫魔法工坊:快速搭建你的二次元创作平台
  • 探寻2026年贵阳诚信的网络营销培训学校,怎么选择更合适 - myqiye
  • 聊聊江苏宇灿智能装备技术水平怎么样,其管道加热器值得推荐吗 - 工业推荐榜
  • 春联生成模型-中文-base内存优化:解决大并发下的显存溢出问题
  • Qwen2-VL-2B-Instruct保姆级教程:Pillow+Sentence-Transformers环境配置全步骤
  • AWPortrait-Z快速入门:3步搞定你的第一张AI肖像照
  • RVC语音变声器教育应用:语言学习发音纠正与语音模仿训练
  • 分布式存储系统设计
  • 释放创意:用MiniCPM-o-4.5为短视频脚本生成分镜与文案
  • 2026年口碑好的家电展会推荐,专业家电展会服务企业全盘点 - mypinpai
  • ComfyUI Qwen人脸生成图像实战:用AI为老照片生成清晰全身影像
  • Qwen3-TTS-VoiceDesign一键部署:start_demo.sh脚本解析与自定义端口修改方法
  • 2026年南昌性价比高的装修公司推荐,探讨丛一楼装饰设计水平与反馈 - 工业设备
  • 造相-Z-Image保姆级教程:RTX 4090专属,5分钟本地部署文生图系统
  • Qwen1.5-1.8B GPTQ开发环境搭建:IntelliJ IDEA集成指南
  • 讲讲全国高强丝定制专家,中祥线业推荐选吗? - 工业品牌热点
  • 音频处理新神器:Qwen3-TTS-Tokenizer-12Hz快速上手指南
  • 2026最新论文降重教程:免费降AI率指令与3款工具实测数据对比
  • Qwen3-ASR-0.6B语音识别部署案例:政务热线录音智能归档系统