散列表实现(平方探测法)

from 《数据结构与算法分析》

开放地址散列法中,如果有冲突发生,就尝试选择另外单元,直到找出空的单元为止。

更一般的,单元h0(X) ,h1(X),h2(X)等等

hi(X)=(Hash(X)+F(i)) mod TableSize  且 F(0)=0

对开放地址散列表算法来说,装填因子应低于0.5

平方探测法是消除线性探测中的一次聚集问题的冲突解决方法。流行的选择是F(i)=i*i;

定理:如果使用平方探测,且表的大小是素数,那么当表至少有一半是空的时候,总能够插入一个新的元素。

// HashTable_OpenAddressingHash.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#define MinTableSize 5
typedef unsigned int Index;
typedef Index Position;
typedef int ElementType;
struct HashTbl;
typedef struct HashTbl* HashTable;
enum KindOfEntry{Legitimate,Empty,Deleted};
struct HashEntry
{
	ElementType Element;
	enum KindOfEntry Info;
};
typedef struct HashEntry Cell;
struct HashTbl
{
	int TableSize;
	Cell* TheCells;
};
static int NextPrime(int TableSize);
static bool IsPrime(int num);
static int Fmod(int a, int b, int c);

HashTable InitTable(int TableSize);
void error(char* str);
int Hash(ElementType Key, int TableSize);
bool Insert(ElementType Key, HashTable H);
bool Delete(ElementType Key, HashTable H);
HashTable Rehash(HashTable H);
void Release(HashTable H);
void error(char* str)
{
	printf("%s\n", str);
	exit(0);
}
HashTable InitTable(int TableSize)
{
	HashTable H;
	int i;
	if (TableSize < MinTableSize)
		error("TableSize is too small");
	H = (HashTable)malloc(sizeof(HashTbl));
	if (H == NULL)
		error("Out Of Memory");
	H->TableSize = NextPrime(TableSize);
	H->TheCells = (Cell*)malloc(sizeof(struct HashEntry)*sizeof(H->TableSize));
	if (H->TheCells == NULL)
		error("Out Of Memory");
	for (i = 0; i < H->TableSize; i++)
		H->TheCells[i].Info = Empty;
	return H;
}
Position Find(ElementType Key, HashTable H)
{
	Position CurPos=Hash(Key,H->TableSize);
	int CollisionNum=0;
	while (H->TheCells[CurPos].Info != Empty&&
		H->TheCells[CurPos].Element != Key)
	{
		CurPos += 2 * (++CollisionNum) - 1;
		//如果新的定位越过数组,那么可以通过减去TableSize把它拉回数组范围内
		if (CurPos >= H->TableSize)
			CurPos -= H->TableSize;
	}
	return CurPos;
}
int Hash(ElementType Key, int TableSize)
{
	return Key%TableSize;
}
bool Insert(ElementType Key, HashTable H)
{
	Position Pos;
	Pos = Find(Key, H);
	if (H->TheCells[Pos].Info != Legitimate)
	{
		H->TheCells[Pos].Info = Legitimate;
		H->TheCells[Pos].Element = Key;
		return true;
	}
	return false;
}
bool Delete(ElementType Key, HashTable H)
{
	Position P = Find(Key, H);
	//懒惰删除 
	if (H->TheCells[P].Info == Legitimate&&H->TheCells[P].Element == Key)
	{
		H->TheCells[P].Info == Empty;
		return true;
	}
	return false;
}
HashTable Rehash(HashTable H)
{
	int i = 0;
	int OldSize = H->TableSize;
	Cell* OldCells = H->TheCells;
	H = InitTable(2 * OldSize);
	for (i = 0; i < OldSize; i++)
	{
		if (OldCells[i].Info == Legitimate)
		{
			Insert(OldCells[i].Element, H);
		}
	}
	free(OldCells);
	return H;
}
void Release(HashTable H)
{
	free(H->TheCells);
	free(H);
}

static int Fmod(int a, int b, int c)//快速模取幂  
{
	if (b == 1) return a;
	int t = Fmod(a, b / 2, c);
	t = (t * t) % c;
	if (b & 1) t = (t * a) % c;
	return t;
}
static bool IsPrime(int num)//米勒-拉宾算法  
{
	for (int i = 0; i < 100; ++i)
	{
		if (Fmod(rand() % (num - 1) + 1, num - 1, num) != 1)
			//a的取值为[1,num-1],a的值需要变化,所以用到随机函数  
			return false;
	}
	return true;
} 
static int NextPrime(int TableSize)
{
	while (!IsPrime(TableSize))
	{
		TableSize++;
	}
	return TableSize;
}


你可能感兴趣的:(数据结构)