哈希算法的优化(闭散列)

完整代码块

/***************************************/
//Hash_OP.h


#define MAX_SIZE 10

//typedef int DataType;
typedef char *DataType;

typedef int(*PDTInt)(DataType data);//转int类型

typedef enum{ EXIST, EMPTY, DELETE }State;

typedef struct HTElem
{
	DataType _data;
	State _state;
}HTElem;

typedef struct HashTable
{
	HTElem *_pHt;
	int _capacity;
	int _size;//计算哈希表中有效元素的个数
	int _total; //EXIST和DELETEl两个元素之和
	PDTInt _PDTInt;//转int类型
}HashTable, HT;

//哈希表的初始化
void InitHashTable(HT *ht, int capacity, PDTInt pDTInt);

//哈希表的插入
void InsertHashTable(HT *ht, DataType data);

//哈希表的删除
void DeleteHashTable(HT *ht, DataType data);

//哈希表的查找
int FindHashTable(HT *ht, DataType data);

//计算哈希表长度
int SizeHashTable(HT *ht);

//哈希表的判空
int EmptyHashTable(HT *ht);

//计算哈希地址
int FuncHash(HT *ht, DataType data);

//增容
void _CheckCapacity(HT *ht);

//销毁
void DestroyHashTable(HT *ht);

/***************************************/
//Hash_OP.c
#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include "Common.h"

//哈希表的初始化
void InitHashTable(HT *ht, int capacity, PDTInt pDTInt)
{
	assert(ht);
	int i = 0;
	capacity = GetNextPrime(capacity);
	ht->_pHt = (HTElem*)malloc(capacity * sizeof(HTElem));
	if (NULL == ht->_pHt)
	{
		assert(0);
		return;
	}

	ht->_capacity = capacity;
	for (; i < capacity; ++i)
		ht->_pHt[i]._state = EMPTY;
	ht->_size = 0;
	ht->_total = 0;
	ht->_PDTInt = pDTInt;
}

//增容
void _CheckCapacity(HT *ht)
{
	assert(ht);
	int hashAddr = 0;

	//哈希负载因子
	if (ht->_total * 10 / ht->_capacity >= 7)
	{
		//1.开辟新空间
		int oldCapacity = ht->_capacity;
		int newCapacity = GetNextPrime(ht->_capacity);
		HTElem *pNew = (HTElem *)malloc(newCapacity * sizeof(HTElem));
		int i = 0;
		if (NULL == pNew)
		{
			assert(0);
			return;
		}

		//2.拷贝元素
		for (i = 0; i < newCapacity; ++i)
			pNew[i]._state = EMPTY;

		//只拷贝状态为存在的元素
		ht->_capacity = newCapacity;
		for (i = 0; i < oldCapacity; ++i)
		{
			if (EXIST != ht->_pHt[i]._state)
				continue;

			hashAddr = FuncHash(ht, ht->_pHt[i]._data);

			//找存储位置
			while (EMPTY != ht->_pHt[hashAddr]._state)
			{
#if 0
				//线性探测
				hashAddr++;
				if (hashAddr == ht->_capacity)//越界了,从头开始访问
					hashAddr = 0;
#else
				//二次探测
				i++;
				hashAddr = hashAddr + 2 * i + 1;
				if (hashAddr >= ht->_capacity)
					hashAddr %= ht->_capacity;
#endif
			}

			//插入元素
			ht->_pHt[hashAddr]._data = ht->_pHt[i]._data;
			ht->_pHt[hashAddr]._state = EXIST;
		}
		//3.释放旧空间
		free(ht->_pHt);
		ht->_pHt = pNew;
		ht->_total = ht->_size;
	}
}

//哈希表的插入
void InsertHashTable(HT *ht, DataType data)
{
	int hashAddr;
	int i = 0;
	assert(ht);

	//检测容量
	_CheckCapacity(ht);

	//计算哈希地址
	hashAddr = FuncHash(ht, data);

	//找存储位置
	while (EMPTY != ht->_pHt[hashAddr]._state)
	{
		if (EXIST == ht->_pHt[hashAddr]._state)
		{
			if (data == ht->_pHt[hashAddr]._data)
				return;
		}
#if 0
		//线性探测
		hashAddr++;
		if (hashAddr == ht->_capacity)//越界了,从头开始访问
			hashAddr = 0;
#else
		//二次探测
		i++;
		hashAddr = hashAddr + 2 * i + 1;
		if (hashAddr >= ht->_capacity)
			hashAddr %= ht->_capacity;
#endif
	}

	//插入元素
	ht->_pHt[hashAddr]._data = data;
	ht->_pHt[hashAddr]._state = EXIST;
	ht->_size++;
	ht->_total++;
}

//哈希表的删除
void DeleteHashTable(HT *ht, DataType data)
{
	assert(ht);
	if (-1 != FindHashTable(ht, data))
	{
		ht->_pHt[FindHashTable(ht, data)]._state = DELETE;
		ht->_size--;
	}
}

//哈希表的查找
int FindHashTable(HT *ht, DataType data)
{
	int hashAddr;
	int i = 0;
	assert(ht);
	hashAddr = FuncHash(ht, data);

	while (EMPTY != ht->_pHt[hashAddr]._state)
	{
		if (EXIST == ht->_pHt[hashAddr]._state)
		{
			if (data == ht->_pHt[hashAddr]._data)
				return hashAddr;
		}

#if 0
		hashAddr++;
		if (hashAddr == ht->_capacity)//越界了,从头开始访问
			hashAddr = 0;
#else
		//二次探测
		i++;
		hashAddr = hashAddr + 2 * i + 1;
		if (hashAddr >= ht->_capacity)
			hashAddr %= ht->_capacity;
#endif
	}
	return -1;
}

//计算哈希表长度
int SizeHashTable(HT *ht)
{
	assert(ht);
	return ht->_size;
}

//哈希表的判空
int EmptyHashTable(HT *ht)
{
	assert(ht);
	return 0 == ht->_size;
}

//计算哈希地址
int FuncHash(HT *ht, DataType data)
{
	assert(ht);
	return ht->_PDTInt(data) % ht->_capacity;
}


//销毁
void DestroyHashTable(HT *ht)
{
	assert(ht);
	free(ht->_pHt);
	ht->_pHt = NULL;
	ht->_capacity = 0;
	ht->_size = 0;
	ht->_total;
}




/***************************************/
//Common.h

#pragma once

//素数表
unsigned long GetNextPrime(unsigned long prime);

//字符串类型
unsigned long StrToINT(const char * str);

//默认转化方法
unsigned long DefToINT(long data);


/
//Common.c
#define PRIME_SIZE 28

//素数表
unsigned long GetNextPrime(unsigned long prime)
{

	// 使用素数表对齐做哈希表的容量,降低哈希冲突      
	static const unsigned long _PrimeList [PRIME_SIZE] =     
	{         
		53ul,         97ul,         193ul,       389ul,       769ul,         
		1543ul,       3079ul,       6151ul,      12289ul,     24593ul,         
		49157ul,      98317ul,      196613ul,    393241ul,    786433ul,         
		1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,         
		50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,         
		1610612741ul, 3221225473ul, 4294967291ul     
	}; 

	int i = 0;
	for (i = 0; i < PRIME_SIZE; ++i)
	{
		if (_PrimeList[i] > prime)
			return _PrimeList[i];
	}

	return _PrimeList[PRIME_SIZE - 1];
}

//字符串类型
unsigned long StrToINT(const char * str)
{
	unsigned int seed = 131; // 31 131 1313 13131 131313
	unsigned int hash = 0;      
	while (*str)     
	{ 
		hash = hash * seed + (*str++); 
	}      
	return (hash & 0x7FFFFFFF);
}

//默认转化方法
unsigned long DefToINT(long data)
{
	return data;
}



/***************************************/
//test.c
#include "Hash_OP.h"
#include <stdio.h>

void TestHash_OP()
{
	HashTable ht;
	InitHashTable(&ht, 10, DefToINT);
	InsertHashTable(&ht, 23);
	InsertHashTable(&ht, 14);
	InsertHashTable(&ht, 35);
	InsertHashTable(&ht, 22);
	InsertHashTable(&ht, 27);
	InsertHashTable(&ht, 17);
	
	printf("size = %d\n", SizeHashTable(&ht));
	if (-1 == FindHashTable(&ht, 17))
		printf("17 这个元素不存在\n");
	else
		printf("17 这个元素存在\n");
	
	if (-1 == FindHashTable(&ht, 37))
		printf("37 这个元素不存在\n");
	else
		printf("37 这个元素存在\n");



	InitHashTable(&ht, 10, StrToINT);
	InsertHashTable(&ht, "23");
	InsertHashTable(&ht, "14");
	InsertHashTable(&ht, "35");
	InsertHashTable(&ht, "22");
	InsertHashTable(&ht, "27");
	InsertHashTable(&ht, "17");
	
	printf("size = %d\n", SizeHashTable(&ht));
	if (-1 == FindHashTable(&ht, "17"))
		printf("字符17 这个元素不存在\n");
	else
		printf("字符17 这个元素存在\n");
	
	if (-1 == FindHashTable(&ht, "37"))
		printf("字符37 这个元素不存在\n");
	else
		printf("字符37 这个元素存在\n");
	DestroyHashTable(&ht);
}

int main()
{
	TestHash_OP();
	system("pause");
	return 0;
}

结果输出:
在这里插入图片描述


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值