哈希表算法实现

               

哈希表算法实现


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


环境:

主机:WINXP

开发环境:MINGW


说明:

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


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


源代码:

/**********************************************************************         哈希表算法实现*      (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 = 0uint16_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 = 0uint16_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 = 0uint8_t i = 0uint8_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 = 0uint8_t root = 0uint8_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;}





           

猜你喜欢

转载自blog.csdn.net/qq_44925357/article/details/89511807