環境:node
主機:WINXP程序員
開發環境:MINGW算法
說明:數組
本程序創建的哈希表示意圖:數據結構
哈希函數爲對哈希表長取餘app
源代碼:函數
- /*********************************************************************
- * 哈希表算法實現
- * (c)copyright 2013,jdh
- * All Right Reserved
- *文件名:main.c
- *程序員:jdh
- **********************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
-
- /*********************************************************************
- * 宏定義
- **********************************************************************/
-
- /*********************************************************************
- * 數據類型重定義
- **********************************************************************/
-
- #define uint8_t unsigned char
- #define uint16_t unsigned short
- #define uint32_t unsigned long
-
- /*********************************************************************
- * 哈希表長度
- **********************************************************************/
-
- #define HASH_TABLE_LEN 100
-
- /*********************************************************************
- * 數據結構
- **********************************************************************/
- //鏈表節點
- typedef struct _Link_Node
- {
- uint16_t id;
- uint16_t data;
- struct _Link_Node *next;
- }Link_Node,*Link_Node_Ptr;
-
- //哈希表頭
- typedef struct _Hash_Header
- {
- struct _Link_Node *next;
- }Hash_Header,*Hash_Header_Ptr;
-
- /*********************************************************************
- * 全局變量
- **********************************************************************/
-
- //哈希表
- Hash_Header_Ptr Hash_Table[HASH_TABLE_LEN];
-
- /*********************************************************************
- * 函數
- **********************************************************************/
-
- /*********************************************************************
- * 哈希表函數
- *說明:
- *1.用哈希函數生成id對應的哈希表中的位置
- 輸入:id
- 返回:位置
- **********************************************************************/
-
- uint8_t hash_func(uint16_t id)
- {
- uint8_t pos = 0;
-
- pos = id % HASH_TABLE_LEN;
-
- return pos;
- }
-
- /*********************************************************************
- * 初始化節點
- *返回:結點指針
- **********************************************************************/
-
- Link_Node_Ptr init_link_node(void)
- {
- Link_Node_Ptr node;
-
- //申請節點
- node = (Link_Node_Ptr) malloc(sizeof(Link_Node));
- //初始化長度爲0
- node->next = NULL;
-
- return node;
- }
-
- /*********************************************************************
- * 初始化哈希表頭結點
- *返回哈希表頭結點指針
- **********************************************************************/
-
- Hash_Header_Ptr init_hash_header_node(void)
- {
- Hash_Header_Ptr node;
-
- //申請節點
- node = (Hash_Header_Ptr) malloc(sizeof(Hash_Header));
- //初始化長度爲0
- node->next = NULL;
-
- return node;
- }
-
-
- /*********************************************************************
- * 哈希表初始化
- *說明:
- *1.初始化哈希表Hash_Table
- *2.哈希表長度最大不能超過256
- **********************************************************************/
-
- void init_hash_table(void)
- {
- uint8_t i = 0;
-
- for (i = 0;i < HASH_TABLE_LEN;i++)
- {
- Hash_Table[i] = init_hash_header_node();
- Hash_Table[i]->next = NULL;
- }
- }
-
- /*********************************************************************
- * 在哈希表增長節點
- *說明:
- *1.在哈希表的某個鏈表末增長數據
- 輸入:new_node:新節點
- **********************************************************************/
-
- void append_link_node(Link_Node_Ptr new_node)
- {
- Link_Node_Ptr node;
- uint8_t pos = 0;
-
- //新節點下一個指向爲空
- new_node->next = NULL;
-
- //用哈希函數得到位置
- pos = hash_func(new_node->id);
-
- //判斷是否爲空鏈表
- if (Hash_Table[pos]->next == NULL)
- {
- //空鏈表
- Hash_Table[pos]->next = new_node;
- }
- else
- {
- //不是空鏈表
- //獲取根節點
- node = Hash_Table[pos]->next;
-
- //遍歷
- while (node->next != NULL)
- {
- node = node->next;
- }
-
- //插入
- node->next = new_node;
- }
- }
-
- /*********************************************************************
- * 在哈希表查詢節點
- *說明:
- *1.知道在哈希表某處的單鏈表中,並開始遍歷.
- *2.返回的是查詢節點的前一個節點指針.這麼作是爲了作刪除操做.
- 輸入:pos:哈希表數組位置,從0開始計數
- id:所須要查詢節點的id
- root:若是是根節點,則*root = 1,不然爲0
- 返回:所需查詢的節點的前一個節點指針,若是是根節點則返回根節點,失敗返回0
- **********************************************************************/
-
- Link_Node_Ptr search_link_node(uint16_t id,uint8_t *root)
- {
- Link_Node_Ptr node;
- uint8_t pos = 0;
-
- //用哈希函數得到位置
- pos = hash_func(id);
-
- //獲取根節點
- node = Hash_Table[pos]->next;
-
- //判斷單鏈表是否存在
- if (node == NULL)
- {
- return 0;
- }
-
- //判斷是不是根節點
- if (node->id == id)
- {
- //是根節點
- *root = 1;
- return node;
- }
- else
- {
- //不是根節點
- *root = 0;
- //遍歷
- while (node->next != NULL)
- {
- if (node->next->id == id)
- {
- return node;
- }
- else
- {
- node = node->next;
- }
- }
-
- return 0;
- }
- }
-
- /*********************************************************************
- * 在哈希表刪除節點
- *說明:
- *1.刪除的不是當前節點,而是當前節點後的一個節點
- 輸入:node:刪除此節點後面的一個節點
- new_node:新節點
- **********************************************************************/
-
- void delete_link_node(Link_Node_Ptr node)
- {
- Link_Node_Ptr delete_node;
-
- //重定向須要刪除的前一個節點
- delete_node = node->next;
- node->next = delete_node->next;
-
- //刪除節點
- free(delete_node);
- delete_node = NULL;
- }
-
- /*********************************************************************
- * 在哈希表刪除根節點
- 輸入:node:根節點
- **********************************************************************/
-
- void delete_link_root_node(Link_Node_Ptr node)
- {
- uint8_t pos = 0;
-
- //用哈希函數得到位置
- pos = hash_func(node->id);
-
- //哈希表頭清空
- if (node != NULL)
- {
- Hash_Table[pos]->next = node->next;
- //刪除節點
- free(node);
- node = NULL;
- }
- }
-
- /*********************************************************************
- * 得到哈希表中全部節點數
- 輸入:node:根節點
- **********************************************************************/
-
- uint16_t get_node_num(void)
- {
- Link_Node_Ptr node;
- uint16_t i = 0;
- uint16_t num = 0;
-
- //遍歷
- for (i = 0;i < HASH_TABLE_LEN;i++)
- {
- //獲取根節點
- node = Hash_Table[i]->next;
- //遍歷
- while (node != NULL)
- {
- num++;
- node = node->next;
- }
- }
-
- return num;
- }
-
- /*********************************************************************
- * 從哈希表中得到對應序號的節點
- *參數:index:序號.從1開始,最大值爲節點總數值
- * root:若是是根節點,則*root = 1,不然爲0
- 返回:所需查詢的節點的前一個節點指針,若是是根節點則返回根節點,失敗返回0
- **********************************************************************/
-
- Link_Node_Ptr get_node_from_index(uint16_t index,uint8_t *root)
- {
- Link_Node_Ptr node;
- uint16_t i = 0;
- uint16_t num = 0;
-
- //遍歷
- for (i = 0;i < HASH_TABLE_LEN;i++)
- {
- //獲取根節點
- node = Hash_Table[i]->next;
- //判斷單鏈表是否存在
- if (node == NULL)
- {
- continue;
- }
-
- //根節點
- num++;
- if (num == index)
- {
- //是根節點
- *root = 1;
- return node;
- }
-
- //遍歷
- while (node->next != NULL)
- {
- num++;
- if (num == index)
- {
- //不是根節點
- *root = 0;
- return node;
- }
- node = node->next;
- }
- }
-
- return 0;
- }
-
- /*********************************************************************
- * 刪除hash表中全部節點
- **********************************************************************/
-
- void drop_hash()
- {
- Link_Node_Ptr node;
- uint16_t i = 0;
- Link_Node_Ptr node_next;
-
- //遍歷
- for (i = 0;i < HASH_TABLE_LEN;i++)
- {
- //獲取根節點
- node = Hash_Table[i]->next;
-
- while (1)
- {
- //判斷單鏈表是否存在
- if (node == NULL)
- {
- //不存在
- Hash_Table[i]->next = NULL;
- break;
- }
-
- //根節點下一個節點
- node_next = node->next;
- //刪除根節點
- free(node);
- //重指定根節點
- node = node_next;
- }
- }
- }
-
- /*********************************************************************
- * 輸出全部節點
- **********************************************************************/
-
- void printf_hash()
- {
- Link_Node_Ptr node;
- uint8_t root = 0;
- uint8_t i = 0;
- uint8_t num = 0;
-
- printf("-------------打印hash表-------------\n");
-
- num = get_node_num();
- for (i = 1;i <= num;i++)
- {
- node = get_node_from_index(i,&root);
- if (node != 0)
- {
- if (root)
- {
- printf("根節點:節點號%d,id爲%d\n",i,node->id);
- }
- else
- {
- printf("普通節點:節點號%d,id爲%d\n",i,node->next->id);
- }
- }
- }
- }
-
- /*********************************************************************
- * 主函數
- *說明:實現對哈希表的新建,創建節點,查詢及增長,刪除節點的操做
- **********************************************************************/
-
- int main()
- {
- Link_Node_Ptr node;
- uint8_t temp = 0;
- uint8_t root = 0;
- uint8_t i = 0;
-
- init_hash_table();
-
- //插入數據id = 1,data = 2;
- node = init_link_node();
- node->id = 1;
- node->data = 2;
- append_link_node(node);
-
- //查詢節點數
- printf("1節點數爲%d\n",get_node_num());
-
- node = init_link_node();
- node->id = 100;
- node->data = 101;
- append_link_node(node);
-
- node = init_link_node();
- node->id = 1002;
- node->data = 1001;
- append_link_node(node);
-
- node = init_link_node();
- node->id = 10000;
- node->data = 10001;
- append_link_node(node);
-
- node = init_link_node();
- node->id = 1000;
- node->data = 10001;
- append_link_node(node);
-
- node = init_link_node();
- node->id = 2;
- node->data = 10001;
- append_link_node(node);
-
- //查詢節點數
- printf("2節點數爲%d\n",get_node_num());
-
- //查詢id = 1000;
- node = search_link_node(100,&temp);
- if (node != 0)
- {
- if (temp == 0)
- {
- printf("刪除普通節點:所需查詢id的值爲%d,數據爲%d\n",node->next->id,node->next->data);
-
- //刪除
- delete_link_node(node);
- }
- else
- {
- //根節點
- printf("刪除根節點所需查詢id的值爲%d,數據爲%d\n",node->id,node->data);
-
- //刪除
- delete_link_root_node(node);
- }
- }
- else
- {
- printf("查詢失敗\n");
- }
-
- //查詢id = 1000;
- node = search_link_node(1001,&temp);
- if (node != 0)
- {
- if (temp == 0)
- {
- printf("所需查詢id的值爲%d\n",node->next->data);
- }
- else
- {
- //根節點
- printf("所需查詢id的值爲%d\n",node->data);
- }
- }
- else
- {
- printf("查詢失敗\n");
- }
-
- //查詢節點數
- printf("節點數爲%d\n",get_node_num());
-
- printf_hash();
-
-
- getchar();
- return 0;
- }
本文博客連接:http://blog.csdn.net/jdh99,做者:jdh,轉載請註明.ui