哈希表算法实现

转自:http://blog.csdn.net/jdh99/article/details/8490704

哈希表算法实现


本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.


环境:

主机:WINXP

开发环境:MINGW


说明:

本程序建立的哈希表示意图:

哈希表算法实现_第1张图片

哈希函数为对哈希表长取余


源代码:

[cpp]  view plain  copy
 
  1. /********************************************************************* 
  2. *                          哈希表算法实现 
  3. *                       (c)copyright 2013,jdh 
  4. *                         All Right Reserved 
  5. *文件名:main.c 
  6. *程序员:jdh 
  7. **********************************************************************/  
  8.   
  9. #include   
  10. #include   
  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. }

你可能感兴趣的:(hash,哈希,C++)