第五章第二节(散列开放定址法)

开放定址散列法:是另一种不用链表解决冲突的方法,在开放定址散列算法系统中,如果有冲突发生,那么就要尝试选择另外的单元,直到找出空的单元为止。
公式 : hi ( X ) = ( hash(X)+F(i) ) mod TableSize
关键字X的位置等于 Hash函数返回的位置在加上F(i)的位置 Mod TableSize

线性探测法:F(i) = i ,这相当于逐个探测每个单元(必要时可以绕回)以查找出一个空单元。
平方探测法: F(i) = i²,平方探测法冲突函数为二次函数的探测方法。F(i) = i²,防止多次冲突,形成一次聚集。

以下代码是 平方探测法的实现:

数据结构和主要函数声明

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

typedef unsigned int Index;
typedef Index Postion;
typedef char* ElementType;
enum KindOfEntry { Legitimate, Empty, Deleted };	//标记表中单元的状态

struct HashEntry {
	char element[20];	//实体
	KindOfEntry Inof;		//存储状态
};
typedef struct HashEntry Cell;
struct HashTbl {	//哈希表结构
	int TableSize;	
	Cell* TheCells;		//用链表存储表结构
};
typedef struct HashTbl *HashTable;

//函数声明
HashTable InitializeTable(int Table);	//初始化哈希表
void DestroyTable(HashTable H);			//销毁哈希表
Postion Find(ElementType key, HashTable H);	//查找
void Insert(ElementType key, HashTable H);	//插入
void Delete(ElementType key,HashTable H);	//删除
int NextPrime(int TableSize);			//寻找素数函数
int Hash(const char *key, int tableSize);	//哈希函数

主要函数:哈希函数与素数函数

int Hash(const char *key, int tableSize) {
	//哈希函数
	unsigned int hashVal = 0;
	while (*key != NULL) {
		hashVal = (hashVal << 5) + *key++;
	}
	return hashVal % tableSize;
}
int NextPrime(int TableSize) {
	//寻找素数函数
	int i, j, flag;
	i = TableSize;
	while (1) {
		flag = 1;
		for (j = 2; j <= sqrt(i); j++) {
			if (i%j == 0) {
				flag = 0;
				break;
			}
		}
		if (flag == 1) {
			break;
		}
		i++;
	}
	return i;
}

初始化函数:对每个单元记录一个标记,方便编程,初始化时,把每个单元的标记置为Empty

HashTable InitializeTable(int TableSize) {	//初始化
	HashTable H;
	int i;
	H = (HashTable)malloc(sizeof(struct HashTbl));
	H->TableSize = NextPrime(TableSize);
	H->TheCells = (Cell*)malloc(sizeof(struct HashEntry)*H->TableSize);
	for (i = 0; i < H->TableSize; i++) {	//把每一个单元标记为空。
		H->TheCells[i].Inof = Empty;
	}
	return H;
}

查找函数Find

Postion Find(ElementType key,HashTable H) {		
	//从哈希表中查找一个元素,若存在,返回位置,不存在,返回要下一个空的位置
	Postion CurrentPos;
	int CollisionNum;		//相当于i
	CollisionNum = 0;
	CurrentPos = Hash(key, H->TableSize);	//获取哈希函数散列的位置
	while (H->TheCells[CurrentPos].Inof != Empty && strcmp(H->TheCells[CurrentPos].element,key)) {
		//如果位置的元素为空或者位置元素等于要查找的关键字,返回该位置。
		//否则,平方探测 hash(X)+F(i),F(i) = i²
		CurrentPos += 2 * ++CollisionNum - 1;
		if (CurrentPos >= H->TableSize) {
			CurrentPos %= H->TableSize;
		}
	}
	return CurrentPos;	//返回位置
}

插入函数,删除函数,销毁函数

void Insert(ElementType key, HashTable H) {	//插入一个元素到哈希表中
	Postion Pos;
	Pos = Find(key, H);	//如果哈希表中没有该关键字,则找到要插入的位置,否则,返回已存在的位置。
	if (H->TheCells[Pos].Inof != Legitimate) {	//如果未插入,则进行插入
		strcpy_s(H->TheCells[Pos].element, strlen(key) + 1, key);
		H->TheCells[Pos].Inof = Legitimate;	//标记设为Legitimate,表示存在数据
	}
}

void Delete(ElementType key, HashTable H) {	//从哈希表中删除一个元素
	Postion Pos;
	Pos = Find(key, H);
	if (H->TheCells[Pos].Inof == Legitimate) {	
		//懒惰删除,如果要查找的关键字存在,则把该单元标记为空
		H->TheCells[Pos].Inof = Empty;	
	}
}

void DestroyTable(HashTable H) {	//销毁哈希表
	free(H->TheCells);		//将哈希节点中的存储数据的空间释放
	free(H);				//将哈希节点释放空间,完成删除操作。
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值