C语言之哈希表

写在前面:项目中用一张哈希表来存储设备的属性等信息,用到了哈希表这块,因为对哈希表用的并不是太多,认识没有那么深刻,所以,这里花时间对哈希总结以及写代码调试了一下,加深点印象。

正文:

1、哈希表的作用:为了根据数据部分的关键内容,计算出对应节点完整数据的内存地址。如果用链表的话,链表如果长度很长,就会需要花费较多的时间来遍历链表。为了解决效率问题,哈希表应运而生。

2、哈希表的排布状况,画了一张图,凑合看吧。

从上图可以看出,哈希表的每一个位置的头结点都可以往后延伸成一张链表的形式。

3、剩下的都在代码里了,也是花时间调了几个小时的,注释已经很详细了。

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>

#define HARSH_TABLE_MAX_SIZE   (1000) // 哈希数组的最大元素个数

typedef struct HarshNode_struct HarshNode;

// 定义一个哈希表的节点
struct HarshNode_struct
{
	char * sKey;   // [sKey,nvalue]是一对键值对
	int nValue;
	HarshNode *pNext;
};

HarshNode * harshTable[HARSH_TABLE_MAX_SIZE]; // 哈希表数组
unsigned int g_harsh_table_size = 0x0;



//初始化哈希表
void harsh_table_init(void)
{
	int i = 0x0;
	memset(harshTable,0,sizeof(HarshNode *)*HARSH_TABLE_MAX_SIZE);
	g_harsh_table_size = 0x0;

}


// string harsh function
unsigned int harsh_table_harsh_string(const char * sKey)
{
	const unsigned  char* p =  (const unsigned  char*) sKey;
	unsigned int value = *p;

	if(value)
	{
		for( p += 1; *p != '\0'; p++)
		{
			value = (value << 5) - value + *p;  
		}
	}

	return value;

}


//根据键值对向哈希表中添加节点,如果skey已经存在则直接更新键值nValue
//添加成功返回0,添加失败返回-1
int harsh_table_insert_node(const char * sKey, int nValue)
{
	HarshNode * pHarshNodeHead   = NULL;
	HarshNode * pNewNode = NULL; 
	unsigned int pos = 0x0;

	if((g_harsh_table_size >= HARSH_TABLE_MAX_SIZE )||(NULL  == sKey))
		return -1;
	
	 pos =  harsh_table_harsh_string(sKey) % HARSH_TABLE_MAX_SIZE; //用这种方法计算sKey在哈希数组中对应的位置

	 printf("harsh_table_insert_node : pos = %d\n",pos);

	pHarshNodeHead = harshTable[pos];

	if(NULL == pHarshNodeHead)
	   printf("harsh_table_insert_node:NULL == pHarshNodeHead\n");	

	while(NULL != pHarshNodeHead )  // 如果这个位置对应的不是这一串中最后一个节点的话,那就要向后移动了
    {
		if(strcmp(pHarshNodeHead->sKey,sKey) == 0) //如果这个键值对已经存在,只更新键值即可
		{
			pHarshNodeHead ->nValue = nValue;

			return 0;
		}

		pHarshNodeHead = pHarshNodeHead->pNext;  //向后移动,肯定会有NULL的时候
	
	}

	pNewNode = (HarshNode *)malloc(sizeof(HarshNode)); //申请一块HarshNode 大小的内存
	if(NULL == pNewNode)
    {
		return -1;
	}
	memset(pNewNode,0,sizeof(HarshNode));

	pNewNode ->sKey = (char *)malloc(strlen(sKey) + 1); //申请一块sKey大小的内存
	if(NULL == pNewNode ->sKey )
	{
		return -1;
	}
	memset(pNewNode ->sKey,0,strlen(sKey) + 1);

	strcpy(pNewNode ->sKey,sKey); //将sKey的内容赋给 pNewNode -> sKey
	pNewNode ->nValue = nValue; //键值也复制过来

	pNewNode ->pNext = NULL; //由于是新节点,也是尾节点,所以pNext指向NULL

	pHarshNodeHead  = pNewNode;
	harshTable[pos] = pHarshNodeHead; //最后一定要让数组中的这个位置指向这个头指针

	g_harsh_table_size ++;

	return 0;


}


//打印数组中对应的某个位置的那一串哈希值
void print_harsh_node(int pos)
{
	HarshNode * pHarshNodeHead   = NULL;

	if(pos >= HARSH_TABLE_MAX_SIZE)
		return;

	pHarshNodeHead = harshTable[pos];

	if(NULL == pHarshNodeHead)
	   printf("NULL == pHarshNodeHead\n");	
	while(NULL != pHarshNodeHead)
    {
		printf("come here \n");
		printf("Position:%d, sKey:%s, nValue:%d \n",pos,pHarshNodeHead->sKey,pHarshNodeHead->nValue);
		pHarshNodeHead = pHarshNodeHead->pNext;

	}


}

// 根据键值sKey来查找对应的哈希节点
HarshNode * harsh_table_lookup(const char *sKey)
{
	unsigned int pos = 0x0;
	HarshNode * pHarshHead = NULL;

	if(NULL == sKey)
	{
		return NULL;
	}

	pos = harsh_table_harsh_string(sKey) % HARSH_TABLE_MAX_SIZE; //计算出在哈希数组中的位置

	pHarshHead = harshTable[pos];
	
	while(NULL != pHarshHead)
	{
		if(strcmp(sKey,pHarshHead->sKey) == 0)//找到了
			return pHarshHead;

		pHarshHead = pHarshHead->pNext; // 没有找到的话来到下一个节点
	}

	return NULL;

}



void main(void)
{
	char * pSkey = "abcd";
	int nValue = 1234;
	int ret = -1;
	int pos = 0xffffffff;
	HarshNode * pHarshNode = NULL;

	harsh_table_init();
	ret = harsh_table_insert_node(pSkey,nValue);

	printf("ret = %d\n",ret);


	if(!ret)
    {
		pos = harsh_table_harsh_string(pSkey) % HARSH_TABLE_MAX_SIZE;
		printf("main:  pos = %d\n",pos);
		print_harsh_node(pos);
	}

	pHarshNode = harsh_table_lookup(pSkey);

	if(NULL != pHarshNode)
	{
		printf("Got it: sKey:%s, nValue: %d\n",pHarshNode->sKey,pHarshNode->nValue);
	}

	
}

测试结果如下:

 

 

  • 5
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
哈希表是一种常用的数据结构,可以用来快速查找和插入数据。如果我们想要用C语言实现一个图书的管理系统,可以利用哈希表来存储和管理图书信息。 首先,我们可以定义一个结构体来表示图书的信息,包括书名、作者、出版日期等等。然后,我们可以利用哈希函数将图书的一些特征转化为哈希值,作为图书在哈希表中的索引。 在C语言中,我们可以使用数组和链表来实现哈希表。首先,我们需要定义一个哈希表的大小,也就是数组的大小。然后,我们可以定义一个数组,每个数组元素都是一个链表的头指针。当我们需要插入一个图书时,首先计算出图书的哈希值,然后将图书插入对应链表中的合适位置。当我们需要查找一个图书时,也通过计算哈希值,然后在对应链表中进行查找操作。 实现哈希表的关键是设计一个好的哈希函数,使得哈希值能够平均地分布在哈希表的各个位置上,从而提高查找和插入操作的效率。常见的哈希函数有取余法、折叠法、乘法哈希法等。在实际应用中,我们可以根据图书的特征进行设计,比如可以将书名的ASCII码之和作为哈希值。 除了基本的插入和查找操作,我们还可以实现其他一些功能,比如删除图书、更新图书信息等。当删除一个图书时,可以先计算出哈希值,然后在对应链表中删除该图书节点。当更新一个图书信息时,可以先通过哈希值找到该图书节点,然后进行信息更新操作。 总而言之,C语言可以通过哈希表来实现图书管理系统,提供高效的插入、查找、删除和更新等功能。通过合适的哈希函数设计和良好的数据结构组织,我们可以快速地对图书信息进行操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KiranWang

一起努力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值