哈希表

        哈希表,有时候也被称为散列表。个人认为,hash表是介于链表和二叉树之间的一种中间结构。链表使用十分方便,但是数据查找十分麻烦;二叉树中的数据严格有序,但是这是以多一个指针作为代价的结果。hash表既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。

        哈希利用函数计算出数据应该存放的地址,存入数据,在需要查找数据的时候还是用同样的函数。

       那么如果是通过函数来计算数据的存放地址,那么数据之间的关系存储了吗?实际上这就是第四类逻辑结构,即“集合”。前期提到的三大类数据结构(线性表、树、图)都是对数据之间内部关系非常敏感的。在实际软件开发中,还会有这一种内部结构为松散关系的数据结构,那就是把一批数据作为一个整体,只关注某个数据是否在其中,也就是查找操作,称为“集合”。对于集合来说,既然对它内部数据关系并不敏感,那就可以不处理这些关系信息,而仅仅设法提高查找效率即可。

        把上述思路小结一下,第一,数据结构采用“集合”,第二,定位放置采用“函数”。这种利用函数计算存储地址的集合结构称为hash table;函数被称为“哈希函数”;利用这种结构进行查找的技术称为“哈希查找法”。

       选取某个函数,依照该函数按关键码计算元素的存储位置,并按此存放;查找时。由同一个函数对给定值finddata计算地址,之后在相应的地址单元中读取该元素,这就是哈希查找法,哈希查找法中使用的地址计算函数称为哈希函数,按这个思想构造的表称为哈希表。

       这种存储方法并不是顺序存储,虽然存储空间连续,但是数据并没有连续存放,也不是链式存储,因为存储位置随机,但是并没有启用链表指针。数据仅仅存储在一片内存空间中,并没有额外地存储一批管理数据,所以也不是索引存储。

       哈希方法通常用在较大的数据需求空间下使用较小的实际空间存储,而将大空间地址压缩存储到小空间中,地址计算就无法避免重复的相同结果。这种情况称为“冲突”,而映射到同一个哈希地址上的关键码称为“同义词”。实用编程应用中冲突是不可避免的,只能尽量减少。

根据上面的讨论,可以看到采用哈希方法需要解决以下两个问题:

(1) 构造好的哈希函数。首先要使得所设计的函数要尽可能简单,易于计算和实现,以便提高求地址的速度。另外要使所选函数对关键码计算出的地址在整个地址空间中大致均匀分布,以减少冲突发生的概率。

(2) 制定解决冲突的方案。


a)定义hash表和基本数据节点

typedef struct _NODE
{
	int data;
	struct _NODE* next;
}NODE;

typedef struct _HASH_TABLE
{
	NODE* value[10];
}HASH_TABLE;
b)创建hash表
HASH_TABLE* create_hash_table()
{
	HASH_TABLE* pHashTbl = (HASH_TABLE*)malloc(sizeof(HASH_TABLE));
	memset(pHashTbl, 0, sizeof(HASH_TABLE));
	return pHashTbl;
}
c)在hash表当中寻找数据
NODE* find_data_in_hash(HASH_TABLE* pHashTbl, int data)
{
	NODE* pNode;
	if(NULL ==  pHashTbl)
		return NULL;

	if(NULL == (pNode = pHashTbl->value[data % 10]))
		return NULL;

	while(pNode){
		if(data == pNode->data)
			return pNode;
		pNode = pNode->next;
	}
	return NULL;
}

d)在hash表当中插入数据

STATUS insert_data_into_hash(HASH_TABLE* pHashTbl, int data)
{
	NODE* pNode;
	if(NULL == pHashTbl)
		return FALSE;

	if(NULL == pHashTbl->value[data % 10]){
		pNode = (NODE*)malloc(sizeof(NODE));
		memset(pNode, 0, sizeof(NODE));
		pNode->data = data;
		pHashTbl->value[data % 10] = pNode;
		return TRUE;
	}

	if(NULL != find_data_in_hash(pHashTbl, data))
		return FALSE;

	pNode = pHashTbl->value[data % 10];
	while(NULL != pNode->next)
		pNode = pNode->next;

	pNode->next = (NODE*)malloc(sizeof(NODE));
	memset(pNode->next, 0, sizeof(NODE));
	pNode->next->data = data;
	return TRUE;
}
e)从hash表中删除数据
STATUS delete_data_from_hash(HASH_TABLE* pHashTbl, int data)
{
	NODE* pHead;
	NODE* pNode;
	if(NULL == pHashTbl || NULL == pHashTbl->value[data % 10])
		return FALSE;

	if(NULL == (pNode = find_data_in_hash(pHashTbl, data)))
		return FALSE;

	if(pNode == pHashTbl->value[data % 10]){
		pHashTbl->value[data % 10] = pNode->next;
		goto final;
	}

	pHead = pHashTbl->value[data % 10];
	while(pNode != pHead ->next)
		pHead = pHead->next;
	pHead->next = pNode->next;

final:
	free(pNode);
	return TRUE;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值