哈希表(开放定址法)

一、哈希表概念

由于搜索二叉树中元素存储位置与元素各个关键码之间没有对应的关系,因此在查找一个元素时需要一个一个进行比较,搜索效率取决比较次数。如果构造一个存储结构使它存储位置与关键码能够一一对应,那么查找效率就会高效,即用一样的方法存储和查找关键码。哈希表有毕散列(开放定址法)和开散列(链地址法),本文主讲毕散列。

二、哈希冲突

  • 首先毕散列容量是有限的,当满了时需要扩容,扩容时注意需要重新定址。
  • α是负载因子,α=表中有效元素个数/散列表长,α应严格限制在0.7~0.8以下。
  • 我们可以将元素值模表长,得到的值就是在哈希表存储位置的下标,但是如果该位置已存在元素,我们将在此位置往下探测直到找到可以存储的位置,查找时也通过此法查找。

例:依次插入9   11   23   19   54

三、源代码

1、hash.h

#ifndef _HASH__H_
#define _HASH__H_

#include "stdio.h"
#include "assert.h"
#include "malloc.h"

typedef int KeyType;
typedef int ValueType;
enum Status
{
	EMPTY,   //空
	EXITS,   //非空
	DELETE,  //删除
};
typedef struct HashNode
{
	enum Status _status;  //状态
	KeyType _key;         //值
	ValueType _value;     //冲突的次数
}HashNode;
typedef struct HashTable
{
	HashNode *_tables;
	int _size;   //有效值
	int _len;    //表长
}HashTable;

void HashInit(HashTable* ht, int len);
int HashInsert(HashTable* ht, KeyType key, ValueType value);
HashNode* HashFind(HashTable* ht, KeyType key);
int HashRemove(HashTable* ht, KeyType key);
int HashDestory(HashTable* ht);
void HashPrint(HashTable* ht);
int HashSize(HashTable* ht);
int HashEmpty(HashTable* ht);

#endif

2、hash.c

#include "hash.h"
//初始化
void HashInit(HashTable* ht, int len)
{
	assert(ht);
	ht->_tables = (HashNode*)malloc(sizeof(HashNode)*len);
	for (int i = 0; i < len; i++)
		ht->_tables[i]._status = EMPTY;
	ht->_size = 0;
	ht->_len = len;
}
//插入
int HashInsert(HashTable* ht, KeyType key, ValueType value)
{
	assert(ht);
	int i;
	if (((ht->_size * 10) / ht->_len) == 7)//扩容
	{
		HashTable hash;
		HashInit(&hash, ht->_len * 2);
		for (i = 0; i < ht->_len; i++)
		{
			if (ht->_tables[i]._status == EXITS)
				HashInsert(&hash, ht->_tables[i]._key, 0);
		}
		HashInsert(&hash, key, value);
		ht->_tables = hash._tables;
		ht->_len = hash._len;
		ht->_size = hash._size;
		return 0;
	}
	else
	{
		i = key%ht->_len;
		while (ht->_tables[i]._status == EXITS)//存在元素则向后探测
		{
			if (i == ht->_len)
				i = 0;
			else
			{

				ht->_tables[i]._value++;
				i++;
			}
		}
		ht->_tables[i]._key = key;
		ht->_tables[i]._value = value;
		ht->_size++;
		ht->_tables[i]._status = EXITS;
		return 0;
	}
	return -1;
}
//查找
HashNode* HashFind(HashTable* ht, KeyType key)
{
	assert(ht);
	int i = key%ht->_len;
	while (ht->_tables[i]._status != EMPTY)
	{
		if (ht->_tables[i]._key == key)
		{
			if (ht->_tables[i]._status == DELETE)
				return NULL;
			else
				return &ht->_tables[i];
		}
		else
		{
			if (i == ht->_len)
				i = 0;
			else
				i++;
		}
	}
	return NULL;
}
//删除
int HashRemove(HashTable* ht, KeyType key)
{
	assert(ht);
	HashNode* h = HashFind(ht, key);
	if (h == NULL)
		return -1;
	h->_status = DELETE;
	return 0;
}
//清除
int HashDestory(HashTable* ht)
{
	assert(ht);
	free(ht->_tables);
	ht->_tables = NULL;
	ht->_len = ht->_size = 0;
}
//打印
void HashPrint(HashTable* ht)
{
	assert(ht);
	for (int i = 0; i < ht->_len; i++)
	{
		if (ht->_tables[i]._status == EXITS)
			printf("table[%d]:%d.%d\n", i, ht->_tables[i]._key, ht->_tables[i]._value);
		else
			printf("table[%d]:NULL.NULL\n",i);
	}
}
//哈希表中有效元素个数
int HashSize(HashTable* ht)
{
	return ht->_size;
}
//判断哈希表是否为空
int HashEmpty(HashTable* ht)
{
	return ht->_size == 0 ? 0 : 1;
}

3、写一个测试(test.c)让代码跑起来并加以验证

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值