哈希表算法实现(转)

转自:http://blog.csdn.net/jdh99

源码:

  1 /*********************************************************************
  2 *                           哈希表算法实现
  3 *                        (c)copyright 2013,jdh
  4 *                          All Right Reserved
  5 *文件名:main.c
  6 *程序员:jdh
  7 **********************************************************************/
  8
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11
 12 /*********************************************************************
 13 *                            宏定义
 14 **********************************************************************/
 15
 16 /*********************************************************************
 17 *                            数据类型重定义
 18 **********************************************************************/
 19
 20 #define uint8_t unsigned char
 21 #define uint16_t unsigned short
 22 #define uint32_t unsigned long
 23
 24 /*********************************************************************
 25 *                            哈希表长度
 26 **********************************************************************/
 27
 28 #define HASH_TABLE_LEN    100
 29
 30 /*********************************************************************
 31 *                            数据结构
 32 **********************************************************************/
 33 //链表节点
 34 typedef struct _Link_Node
 35 {
 36     uint16_t id;
 37     uint16_t data;
 38     struct _Link_Node *next;
 39 }Link_Node,*Link_Node_Ptr;
 40
 41 //哈希表头
 42 typedef struct _Hash_Header
 43 {
 44     struct _Link_Node *next;
 45 }Hash_Header,*Hash_Header_Ptr;
 46
 47 /*********************************************************************
 48 *                            全局变量
 49 **********************************************************************/
 50
 51 //哈希表
 52 Hash_Header_Ptr Hash_Table[HASH_TABLE_LEN];
 53
 54 /*********************************************************************
 55 *                            函数
 56 **********************************************************************/
 57
 58 /*********************************************************************
 59 *                            哈希表函数
 60 *说明:
 61 *1.用哈希函数生成id对应的哈希表中的位置
 62 输入:id
 63 返回:位置
 64 **********************************************************************/
 65
 66 uint8_t hash_func(uint16_t id)
 67 {
 68     uint8_t pos = 0;
 69
 70     pos = id % HASH_TABLE_LEN;
 71
 72     return pos;
 73 }
 74
 75 /*********************************************************************
 76 *                            初始化节点
 77 *返回:结点指针
 78 **********************************************************************/
 79
 80 Link_Node_Ptr init_link_node(void)
 81 {
 82     Link_Node_Ptr node;
 83
 84     //申请节点
 85     node = (Link_Node_Ptr) malloc(sizeof(Link_Node));
 86     //初始化长度为0
 87     node->next = NULL;
 88
 89     return node;
 90 }
 91
 92 /*********************************************************************
 93 *                            初始化哈希表头结点
 94 *返回哈希表头结点指针
 95 **********************************************************************/
 96
 97 Hash_Header_Ptr init_hash_header_node(void)
 98 {
 99     Hash_Header_Ptr node;
100
101     //申请节点
102     node = (Hash_Header_Ptr) malloc(sizeof(Hash_Header));
103     //初始化长度为0
104     node->next = NULL;
105
106     return node;
107 }
108
109
110 /*********************************************************************
111 *                            哈希表初始化
112 *说明:
113 *1.初始化哈希表Hash_Table
114 *2.哈希表长度最大不能超过256
115 **********************************************************************/
116
117 void init_hash_table(void)
118 {
119     uint8_t i = 0;
120
121     for (i = 0;i < HASH_TABLE_LEN;i++)
122     {
123         Hash_Table[i] = init_hash_header_node();
124         Hash_Table[i]->next = NULL;
125     }
126 }
127
128 /*********************************************************************
129 *                            在哈希表增加节点
130 *说明:
131 *1.在哈希表的某个链表末增加数据
132 输入:new_node:新节点
133 **********************************************************************/
134
135 void append_link_node(Link_Node_Ptr new_node)
136 {
137     Link_Node_Ptr node;
138     uint8_t pos = 0;
139
140     //新节点下一个指向为空
141     new_node->next = NULL;
142
143     //用哈希函数获得位置
144     pos = hash_func(new_node->id);
145
146     //判断是否为空链表
147     if (Hash_Table[pos]->next == NULL)
148     {
149         //空链表
150         Hash_Table[pos]->next = new_node;
151     }
152     else
153     {
154         //不是空链表
155         //获取根节点
156         node = Hash_Table[pos]->next;
157
158         //遍历
159         while (node->next != NULL)
160         {
161             node = node->next;
162         }
163
164         //插入
165         node->next = new_node;
166     }
167 }
168
169 /*********************************************************************
170 *                            在哈希表查询节点
171 *说明:
172 *1.知道在哈希表某处的单链表中,并开始遍历.
173 *2.返回的是查询节点的前一个节点指针.这么做是为了做删除操作.
174 输入:pos:哈希表数组位置,从0开始计数
175      id:所需要查询节点的id
176      root:如果是根节点,则*root = 1,否则为0
177 返回:所需查询的节点的前一个节点指针,如果是根节点则返回根节点,失败返回0
178 **********************************************************************/
179
180 Link_Node_Ptr search_link_node(uint16_t id,uint8_t *root)
181 {
182     Link_Node_Ptr node;
183     uint8_t pos = 0;
184
185     //用哈希函数获得位置
186     pos = hash_func(id);
187
188     //获取根节点
189     node = Hash_Table[pos]->next;
190
191     //判断单链表是否存在
192     if (node == NULL)
193     {
194         return 0;
195     }
196
197     //判断是否是根节点
198     if (node->id == id)
199     {
200         //是根节点
201         *root = 1;
202         return node;
203     }
204     else
205     {
206         //不是根节点
207         *root = 0;
208         //遍历
209         while (node->next != NULL)
210         {
211             if (node->next->id == id)
212             {
213                 return node;
214             }
215             else
216             {
217                 node = node->next;
218             }
219         }
220
221         return 0;
222     }
223 }
224
225 /*********************************************************************
226 *                            在哈希表删除节点
227 *说明:
228 *1.删除的不是当前节点,而是当前节点后的一个节点
229 输入:node:删除此节点后面的一个节点
230      new_node:新节点
231 **********************************************************************/
232
233 void delete_link_node(Link_Node_Ptr node)
234 {
235     Link_Node_Ptr delete_node;
236
237     //重定向需要删除的前一个节点
238     delete_node = node->next;
239     node->next = delete_node->next;
240
241     //删除节点
242     free(delete_node);
243     delete_node = NULL;
244 }
245
246 /*********************************************************************
247 *                            在哈希表删除根节点
248 输入:node:根节点
249 **********************************************************************/
250
251 void delete_link_root_node(Link_Node_Ptr node)
252 {
253     uint8_t pos = 0;
254
255     //用哈希函数获得位置
256     pos = hash_func(node->id);
257
258     //哈希表头清空
259     if (node != NULL)
260     {
261         Hash_Table[pos]->next = node->next;
262         //删除节点
263         free(node);
264         node = NULL;
265     }
266 }
267
268 /*********************************************************************
269 *                            获得哈希表中所有节点数
270 输入:node:根节点
271 **********************************************************************/
272
273 uint16_t get_node_num(void)
274 {
275     Link_Node_Ptr node;
276     uint16_t i = 0;
277     uint16_t num = 0;
278
279     //遍历
280     for (i = 0;i < HASH_TABLE_LEN;i++)
281     {
282         //获取根节点
283         node = Hash_Table[i]->next;
284         //遍历
285         while (node != NULL)
286         {
287             num++;
288             node = node->next;
289         }
290     }
291
292     return num;
293 }
294
295 /*********************************************************************
296 *                            从哈希表中获得对应序号的节点
297 *参数:index:序号.从1开始,最大值为节点总数值
298 *     root:如果是根节点,则*root = 1,否则为0
299 返回:所需查询的节点的前一个节点指针,如果是根节点则返回根节点,失败返回0
300 **********************************************************************/
301
302 Link_Node_Ptr get_node_from_index(uint16_t index,uint8_t *root)
303 {
304     Link_Node_Ptr node;
305     uint16_t i = 0;
306     uint16_t num = 0;
307
308     //遍历
309     for (i = 0;i < HASH_TABLE_LEN;i++)
310     {
311         //获取根节点
312         node = Hash_Table[i]->next;
313         //判断单链表是否存在
314         if (node == NULL)
315         {
316             continue;
317         }
318
319         //根节点
320         num++;
321         if (num == index)
322         {
323             //是根节点
324             *root = 1;
325             return node;
326         }
327
328         //遍历
329         while (node->next != NULL)
330         {
331             num++;
332             if (num == index)
333             {
334                 //不是根节点
335                 *root = 0;
336                 return node;
337             }
338             node = node->next;
339         }
340     }
341
342     return 0;
343 }
344
345 /*********************************************************************
346 *                            删除hash表中所有节点
347 **********************************************************************/
348
349 void drop_hash()
350 {
351     Link_Node_Ptr node;
352     uint16_t i = 0;
353     Link_Node_Ptr node_next;
354
355     //遍历
356     for (i = 0;i < HASH_TABLE_LEN;i++)
357     {
358         //获取根节点
359         node = Hash_Table[i]->next;
360
361         while (1)
362         {
363             //判断单链表是否存在
364             if (node == NULL)
365             {
366                 //不存在
367                 Hash_Table[i]->next = NULL;
368                 break;
369             }
370
371             //根节点下一个节点
372             node_next = node->next;
373             //删除根节点
374             free(node);
375             //重指定根节点
376             node = node_next;
377         }
378     }
379 }
380
381 /*********************************************************************
382 *                            输出所有节点
383 **********************************************************************/
384
385 void printf_hash()
386 {
387     Link_Node_Ptr node;
388     uint8_t root = 0;
389     uint8_t i = 0;
390     uint8_t num = 0;
391
392     printf("-------------打印hash表-------------\n");
393
394     num = get_node_num();
395     for (i = 1;i <= num;i++)
396     {
397         node = get_node_from_index(i,&root);
398         if (node != 0)
399         {
400             if (root)
401             {
402                 printf("根节点:节点号%d,id为%d\n",i,node->id);
403             }
404             else
405             {
406                 printf("普通节点:节点号%d,id为%d\n",i,node->next->id);
407             }
408         }
409     }
410 }
411
412 /*********************************************************************
413 *                            主函数
414 *说明:实现对哈希表的新建,建立节点,查询及增加,删除节点的操作
415 **********************************************************************/
416
417 int main()
418 {
419     Link_Node_Ptr node;
420     uint8_t temp = 0;
421     uint8_t root = 0;
422     uint8_t i = 0;
423
424     init_hash_table();
425
426     //插入数据id = 1,data = 2;
427     node = init_link_node();
428     node->id = 1;
429     node->data = 2;
430     append_link_node(node);
431
432     //查询节点数
433     printf("1节点数为%d\n",get_node_num());
434
435     node = init_link_node();
436     node->id = 100;
437     node->data = 101;
438     append_link_node(node);
439
440     node = init_link_node();
441     node->id = 1002;
442     node->data = 1001;
443     append_link_node(node);
444
445     node = init_link_node();
446     node->id = 10000;
447     node->data = 10001;
448     append_link_node(node);
449
450     node = init_link_node();
451     node->id = 1000;
452     node->data = 10001;
453     append_link_node(node);
454
455     node = init_link_node();
456     node->id = 2;
457     node->data = 10001;
458     append_link_node(node);
459
460     //查询节点数
461     printf("2节点数为%d\n",get_node_num());
462
463     //查询id = 1000;
464     node = search_link_node(100,&temp);
465     if (node != 0)
466     {
467         if (temp == 0)
468         {
469             printf("删除普通节点:所需查询id的值为%d,数据为%d\n",node->next->id,node->next->data);
470
471             //删除
472             delete_link_node(node);
473         }
474         else
475         {
476             //根节点
477             printf("删除根节点所需查询id的值为%d,数据为%d\n",node->id,node->data);
478
479             //删除
480             delete_link_root_node(node);
481         }
482     }
483     else
484     {
485         printf("查询失败\n");
486     }
487
488     //查询id = 1000;
489     node = search_link_node(1001,&temp);
490     if (node != 0)
491     {
492         if (temp == 0)
493         {
494             printf("所需查询id的值为%d\n",node->next->data);
495         }
496         else
497         {
498             //根节点
499             printf("所需查询id的值为%d\n",node->data);
500         }
501     }
502     else
503     {
504         printf("查询失败\n");
505     }
506
507     //查询节点数
508     printf("节点数为%d\n",get_node_num());
509
510     printf_hash();
511
512
513     getchar();
514     return 0;
515 }
时间: 2024-10-09 22:13:19

哈希表算法实现(转)的相关文章

哈希表算法的编写

哈希算法的编写 hash表,有时候也被称为散列表.个人认为,hash表是介于链表和二叉树之间的一种中间结构.链表使用十分方便,但是数据查找十分麻烦:二叉树中的数据严格有序,但是这是以多一个指针作为代价的结果.hash表既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便. 打个比方来说,所有的数据就好像许许多多的书本.如果这些书本是一本一本堆起来的,就好像链表或者线性表一样,整个数据会显得非常的无序和凌乱,在你找到自己需要的书之前,你要经历许多的查询过程:而如果你对所有的书本进行编号

从头到尾彻底解析哈希表算法

说明:本文分为三部分内容,第一部分为一道百度面试题Top K算法的详解:第二部分为关于Hash表算法的详细阐述:第三部分为打造一个最快的Hash表算法. 第一部分:Top K 算法详解 问题描述 百度面试题: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节. 假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个.一个查询串的重复度越高,说明查询它的用户越多,也就是越热门.),请你统计最热门的10个查

哈希表算法

概述 ??Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值.简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. 理论 http://blog.csdn.net/v_july_v/article/d

Leetcode哈希表算法

LeetCode-python 1.两数之和 难度:简单       类型: 哈希表 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元素. 示例 给定 nums = [2, 7, 11, 15], target = 9因为 nums[0] + nums[1] = 2 + 7 = 9所以返回 [0, 1] 解题思路 用字典保存遍历过的数字和下标寻找

哈希表的理解

哈希表是种数据结构,它可以提供快速的插入操作和查找操作.第一次接触哈希表时,它的优点多得让人难以置信.不论哈希表中有多少数据,插入和删除(有时包括侧除)只需要接近常量的时间即0(1)的时间级.实际上,这只需要几条机器指令. 对哈希表的使用者一一人来说,这是一瞬间的事.哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比树快,树的操作通常需要O(N)的时间级.哈希表不仅速度快,编程实现也相对容易. 哈希表也有一些缺点它是基于数组的,

【转】 哈希表

哈希表是种数据结构,它可以提供快速的插入操作和查找操作.第一次接触哈希表时,它的优点多得让人难以置信.不论哈希表中有多少数据,插入和删除(有时包括侧除)只需要接近常量的时间即0(1)的时间级.实际上,这只需要几条机器指令. 对哈希表的使用者一一人来说,这是一瞬间的事.哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比树快,树的操作通常需要O(N)的时间级.哈希表不仅速度快,编程实现也相对容易. 哈希表也有一些缺点它是基于数组的,

数据结构【哈希表】

哈希表(Hash Table)基本概念 哈希表(Hash Table)是一种根据关键字(Key value)直接访问内存存储位置的数据结构.通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种映射对应关系,这个映射函数叫做散列函数,存放数据的数组叫做散列表. 哈希函数构造方法 哈希表的构造方法是: 假设要存储的数据元素个数为n,设置一个长度为m(m≥n)的连续存储单元,分别以每个数据元素的关键字 Ki(0<= i <=n-1) 为自变量,通过哈希函数 hash(Ki) 把 Ki 映射

浅谈算法和数据结构: 十一 哈希表

在前面的系列文章中,依次介绍了基于无序列表的顺序查找,基于有序数组的二分查找,平衡查找树,以及红黑树,下图是他们在平均以及最差情况下的时间复杂度: 可以看到在时间复杂度上,红黑树在平均情况下插入,查找以及删除上都达到了lgN的时间复杂度. 那么有没有查找效率更高的数据结构呢,答案就是本文接下来要介绍了散列表,也叫哈希表(Hash Table) 什么是哈希表 哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 哈希的思路很简单

【算法与数据结构】哈希表-链地址法

哈希表的链地址法来解决冲突问题 将所有关键字为同义词的记录存储在同一个线性链表中,假设某哈希函数产生的哈希地址在区间[0, m - 1]上,则设立一个至振兴向量 Chain  ChainHash[m]; 数据结构 //链表结点 typedef struct _tagNode { int data; //元素值(关键字) struct _tagNode* next; //下一个结点 }Node, *PNode; //哈希表结点 typedef struct _tagHashTable { //这里