哈希表算法

来源:互联网 发布:淘宝买家好评率100% 编辑:程序博客网 时间:2024/05/19 17:47

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


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


/*********************************************************************

*   哈希表算法实现
* (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 128


/*********************************************************************
* 数据结构
**********************************************************************/
//链表节点
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;

//用哈希函数获得位置
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 != NULL && 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);

//哈希表头清空
Hash_Table[pos]->next = NULL;

//删除节点
free(node);
node = NULL;
}


/*********************************************************************
* 主函数
*说明:实现对哈希表的新建,建立节点,查询及增加,删除节点的操作
**********************************************************************/


int main()
{
Link_Node_Ptr node;
uint8_t temp = 0;

init_hash_table();

//插入数据id = 1,data = 2;
node = init_link_node();
node->id = 1;
node->data = 2;
append_link_node(node);

//插入数据id = 100,data = 101
node = init_link_node();
node->id = 100;
node->data = 101;
append_link_node(node);

//id = 1000,data = 1001
node = init_link_node();
node->id = 1000;
node->data = 1001;
append_link_node(node);

//id = 10000,data = 10001
node = init_link_node();
node->id = 10000;
node->data = 10001;
append_link_node(node);

//查询id = 1000;
node = search_link_node(1000,&temp);
if (node != 0)
{
if (temp == 0)
{
printf("所需查询id的值为%d\n",node->next->data);

//删除
delete_link_node(node);
}
else
{
//根节点
printf("所需查询id的值为%d\n",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");
}

getchar();
return 0;
}
0 0
原创粉丝点击