zoukankan      html  css  js  c++  java
  • 哈希表算法实现(转)

    转自: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表-------------
    ");
    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
    ",i,node->id);
    403             }
    404             else
    405             {
    406                 printf("普通节点:节点号%d,id为%d
    ",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
    ",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
    ",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
    ",node->next->id,node->next->data);
    470             
    471             //删除
    472             delete_link_node(node);
    473         }
    474         else
    475         {
    476             //根节点
    477             printf("删除根节点所需查询id的值为%d,数据为%d
    ",node->id,node->data);
    478             
    479             //删除
    480             delete_link_root_node(node);
    481         }
    482     }
    483     else
    484     {
    485         printf("查询失败
    ");
    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
    ",node->next->data);
    495         }
    496         else
    497         {
    498             //根节点
    499             printf("所需查询id的值为%d
    ",node->data);
    500         }
    501     }
    502     else
    503     {
    504         printf("查询失败
    ");
    505     }
    506     
    507     //查询节点数
    508     printf("节点数为%d
    ",get_node_num());
    509     
    510     printf_hash();
    511     
    512     
    513     getchar();
    514     return 0;
    515 }
  • 相关阅读:
    asp.net保存远程图片
    JS中的转义字符
    SQL_统计某列的和
    SQL Server 出错自动回滚
    SQL中的循环语句_类似FOR循环
    转 C# 控制IE
    抓取html 写正则
    正则截取内容
    用于测试的字符串
    C#关闭IE相应的窗口 .
  • 原文地址:https://www.cnblogs.com/fwst/p/4234191.html
Copyright © 2011-2022 走看看