大家好,欢迎来到IT知识分享网。
1. hash_db.h
1 #ifndef _HASH_DB_H 2 #define _HASH_DB_H 3 4 #include "slist.h" 5 6 typedef unsigned int (*hash_func_t) (const void *key); //哈希函数类型,返回值为整数,参数为关键字 7 struct _hash_db 8 { 9 slist_head_t *p_head; //指向数组首地址 10 unsigned int size; //数组成员数 11 unsigned int value_len; //一条记录的长度 12 unsigned int key_len; //关键字的长度 13 hash_func_t pfn_hash; //哈希函数 14 }; 15 typedef struct _hash_db hash_db_t; //指向哈希表对象的指针类型 16 17 int hash_db_init(hash_db_t *p_hash, //哈希表初始化 18 unsigned int size, 19 unsigned int key_len, 20 unsigned int value_len, 21 hash_func_t pfn_hash); 22 23 int hash_db_add(hash_db_t *p_hash, const void *key,const void *value); //添加记录 24 int hash_db_del(hash_db_t *p_hash, const void *key); //删除记录 25 int hash_db_search(hash_db_t *p_hash, const void *key, void *value); //查找记录 26 int hash_db_deinit(hash_db_t *p_hash); //解初始化 27 28 #endif
2. hash_db.c
1 #include "hash_db.h" 2 #include <stdlib.h> 3 #include <string.h> 4 5 /* 寻找结点的上下文,仅内部使用 */ 6 struct _node_find_ctx 7 { 8 const void *key; //查找关键字 9 unsigned int key_len; //关键字长度 10 slist_node_t *p_result; //用于存储查找到的结点 11 }; 12 13 /** 14 * @brief 遍历链表的回调函数,查找指定结点 15 */ 16 static int __hash_db_node_find (void *p_arg, slist_node_t *p_node) 17 { 18 struct _node_find_ctx *p_info = (struct _node_find_ctx *)p_arg; //用户参数为寻找结点的上下文 19 char *p_mem = (char *)p_node + sizeof(slist_node_t); //关键字存储在结点之后 20 21 if (memcmp(p_mem, p_info->key, p_info->key_len) == 0) 22 { 23 p_info->p_result = p_node; 24 return -1; //找到该结点,终止遍历 25 } 26 return 0; 27 } 28 29 30 /** 31 * @brief 哈希表初始化 32 */ 33 int hash_db_init(hash_db_t *p_hash, 34 unsigned int size, 35 unsigned int key_len, 36 unsigned int value_len, 37 hash_func_t pfn_hash) 38 { 39 int i; 40 if ((p_hash == NULL) || (pfn_hash == NULL)) 41 { 42 return -1; 43 } 44 p_hash->p_head = (slist_head_t *)malloc(size * sizeof(slist_head_t)); 45 if (p_hash->p_head == NULL) 46 { 47 return -1; 48 } 49 for (i = 0; i < size; i++) 50 { 51 slist_init(&p_hash->p_head[i]); 52 } 53 p_hash->size = size; 54 p_hash->key_len = key_len; 55 p_hash->value_len = value_len; 56 p_hash->pfn_hash = pfn_hash; 57 return 0; 58 } 59 60 int hash_db_add(hash_db_t *p_hash, const void *key, const void *value) 61 { 62 int idx = p_hash -> pfn_hash(key); //使用哈希函数通过关键字得到哈希值 63 /* 分配内存,存储链表结点+关键字+记录 */ 64 char *p_mem = (char *)malloc(sizeof(slist_node_t) + p_hash -> key_len + p_hash -> value_len); 65 if (p_mem == NULL) 66 { 67 return -1; 68 } 69 memcpy(p_mem + sizeof(slist_node_t), key, p_hash -> key_len); //存储关键字 70 memcpy(p_mem + sizeof(slist_node_t) + p_hash->key_len, value, p_hash->value_len); //存储记录 71 return slist_add_head(&p_hash -> p_head[idx], (slist_node_t *)p_mem); //将结点加入链表 72 } 73 74 int hash_db_del(hash_db_t *p_hash, const void *key) 75 { 76 int idx = p_hash->pfn_hash(key); //得到关键字对应哈希表的索引 77 struct _node_find_ctx info = {key, p_hash->key_len, NULL}; //设置遍历链表的上下文信息 78 slist_foreach(&p_hash->p_head[idx], __hash_db_node_find, &info); //遍历,寻找关键字对应的结点 79 if (info.p_result != NULL) 80 { 81 slist_del(&p_hash->p_head[idx], info.p_result); //从链表中删除该结点 82 free(info.p_result); //释放结点空间 83 return 0; 84 } 85 return -1; 86 } 87 88 int hash_db_search(hash_db_t *p_hash, const void *key, void *value) 89 { 90 int idx = p_hash->pfn_hash(key); ////得到关键字对应哈希表的索引 91 struct _node_find_ctx info = {key, p_hash->key_len, NULL}; //设置遍历链表的上下文信息 92 slist_foreach(&p_hash->p_head[idx], __hash_db_node_find, &info); //遍历,寻找关键字对应的结点 93 94 if (info.p_result != NULL) 95 { //找到对应结点,将存储的记录值拷贝到用户提供的空间中 96 memcpy(value, (char *)info.p_result+sizeof(slist_node_t)+p_hash->key_len, p_hash->value_len); 97 return 0; 98 } 99 return -1; 100 } 101 102 int hash_db_deinit(hash_db_t *p_hash) 103 { 104 int i; 105 slist_node_t *p_node; 106 for (i = 0; i < p_hash->size; i++) 107 { //释放哈希表中各个表项中存储的所有结点 108 109 while (slist_begin_get(&p_hash->p_head[i]) != slist_end_get(&p_hash->p_head[i])) 110 { 111 p_node = slist_begin_get(&p_hash->p_head[i]); 112 slist_del(&p_hash->p_head[i], p_node); //释放第一个结点 113 free(p_node); 114 } 115 } 116 free(p_hash->p_head); //释放链表头结点数组空间 117 return 0; 118 }
3. demo
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "hash_db.h" 4 5 typedef struct _student 6 { 7 char name[10]; 8 char sex; 9 float height, weight; 10 } student_t; 11 12 int db_id_to_idx(unsigned char id[6]) //通过ID得到数组索引 13 { 14 int i; 15 int sum = 0; 16 for (i = 0; i < 6; i++) 17 { 18 sum += id[0]; 19 } 20 return sum % 250; 21 } 22 23 int student_info_generate(unsigned char *p_id, student_t *p_student) 24 { 25 int i; 26 for (i = 0; i < 6; i++) 27 { //随机产生一个学号 28 p_id[i] = rand(); 29 } 30 for (i = 0; i < 9; i++) 31 { 32 p_student->name[i] = (rand() % ('z' - 'a')) + 'a'; 33 } 34 p_student->name[i]= '\0'; 35 p_student->sex = (rand() & 0x01) ? 'F' : 'M'; 36 p_student->height = (float)rand() / rand(); 37 p_student->weight = (float)rand() / rand(); 38 return 0; 39 } 40 41 int main(void) 42 { 43 student_t stu; 44 unsigned char id[6]; 45 int i; 46 hash_db_t hash_students; 47 48 hash_db_init(&hash_students, 250, 6, sizeof(student_t), (hash_func_t)db_id_to_idx); 49 50 for(i = 0; i < 100; i++) 51 { //添加100个学生信息 52 student_info_generate(id, &stu); //设置学生的信息,当前一随机数作为测试 53 if (hash_db_search(&hash_students, id, &stu) == 0) 54 { //查找到该ID已存在的学生记录 55 printf("该ID的记录已存在!\n"); 56 continue; 57 } 58 printf("增加记录:ID : %02x%02x%02x%02x%02x%02x ",id[0],id[1],id[2],id[3],id[4],id[5]); 59 printf("ؑ信息:%s %c %.2f %.2f\n", stu.name, stu.sex, stu.height, stu.weight); 60 if (hash_db_add(&hash_students, id, &stu) != 0) 61 { 62 printf("添加失败"); 63 } 64 } 65 printf("查找ID为:%02x%02x%02x%02x%02x%02x的信息\n",id[0],id[1],id[2],id[3],id[4],id[5]); 66 if (hash_db_search(&hash_students, id, &stu) == 0) 67 { 68 printf("学生信息:%s %c %.2f %.2f\n", stu.name, stu.sex, stu.height, stu.weight); 69 } 70 else 71 { 72 printf("未找到该ID的记录\n"); 73 } 74 hash_db_deinit(&hash_students); 75 return 0; 76 }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/31705.html