哈希表算法實現



環境:node

主機:WINXP程序員

開發環境:MINGW算法


說明:數組

本程序創建的哈希表示意圖:數據結構


哈希函數爲對哈希表長取餘app


源代碼:函數

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  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. }  

本文博客連接:http://blog.csdn.net/jdh99,做者:jdh,轉載請註明.ui



相關文章
相關標籤/搜索