#include "search.h"
/***********************hash公共方法***********************/
/*
*使用霍纳算法+除留余数法hash字符串,返回0-M之间
* 基数是素数,很牛逼的做法。
*/
static int hashstring(char *v , int M)//以素数127 hash字符串
{
int hash = 0;
int a = 127;//素数hash
for( ; *v != '\0' ; v++){//霍纳算法
hash = (a*hash + *v)%M;
}
return hash;
}
/*
*使用霍纳算法+除留余数法hash字符串,返回0-M之间
* 基数是伪随机序列,很牛逼的做法。
*/
static int hashUniversal(char *v , int M)//通用hash,以伪随机素数 hash字符串
{
int hash = 0;
int a = 31415;//通过a是伪随机序列 hash
int b = 27168;
for( ; *v != '\0' ; v++ ){
hash = (a*hash + *v)%M;
a = a * b % (M-1);
}
return hash;
}
/***********************hash公共方法***********************/
/*******************拉链法实现散列表方法************************/
static SCHashNode* heads;//M矩阵,动态分配指针数组
int SCHCount = 0;//符号表大小
SCHashNode NewNode(SCHashNode head , Key * key , Value val)
{
SCHashNode x = (SCHashNode)malloc(sizeof(struct SCHashnode) );//分配结构体
x->next = head;
x->key = key;
x->val = val;
return x;//将x插入链表头
}
void SeparateChainingHashST_Init()//初始化数组M
{
int i;
heads = (SCHashNode *)malloc(MCount * sizeof(SCHashNode));//分配指针数组
for(i = 0 ; i < MCount ; i++)//初始化为空
heads[i] = NULL;
}
void SeparateChainingHashST_Put(Key * key , Value val)
{
SCHashNode x;
int hash;
hash = hashstring(key , MCount);
#ifdef BEBUG
printf("%s hash is %d\n",key , hash);
#endif
for(x = heads[hash] ; x != NULL ; x = x->next){//遍历命中则更新
if(strcmp(x->key , key) == 0){
x->val = val;
return ;
}
}
heads[hash] = NewNode(heads[hash] , key , val);//未命中插入链表前面
SCHCount++;
}
Value SeparateChainingHashST_Get(Key * key )
{
SCHashNode x;
int hash;
hash = hashstring(key , MCount);
for(x = heads[hash] ; x != NULL ; x = x->next){
if(strcmp(x->key , key) == 0){
return x->val;//命中
}
}
return 0;//未命中
}
int SeparateChainingHashST_Size()
{
return SCHCount;
}
/************************************************************/
/*******************线性探测实现散列表方法************************/
static int UserSetM = 20;//用户设定存储数组大小
static int LPHM = UserSetM;//实际存储数组大小,这个数值会变化,使得散列表的使用率永远都不会查过1/2,减少探测次数。
static LPHCount = 0;//符号表中元素个数
static LPHashNode Heads;//用于动态分配数组
static void ReSize_LPHM(int M)//重新调整数组大小,代价很大,重新分配,重新插入
{
LPHashNode x;
x = heads;//保持原始数组地址
heads = (LPHashNode)malloc(M * sizeof(struct LPHashnode));//重新分配LPHM对应的数组空间
for(i = 0 ; i < LPHM ; i++)//初始化为空
heads[i] = NULL;
for(i = 0 ; i < M ; i++){//将原始数组有键的位置,重新插入
if(x[i].key != NULL)
LinearProbingHashST_Put(x[i].key , x[i].val);
}
free(x);//释放原始数组位置。
}
void LinearProbingHashST_Init()
{
int i;
Heads = (LPHashNode)malloc(LPHM * sizeof(struct LPHashnode));//分配LPHM对应的数组空间
for(i = 0 ; i < LPHM ; i++)//初始化为空
Heads[i] = NULL;
}
void LinearProbingHashST_Put(Key* key , Value val)
{
int i;
if(LPHCount > LPHM / 2){//保证使用率不大于1/2.
LPHM = 2*LPHM;//扩大两倍
Resize_LPHM(LPHM);//重新调整
}
i = hashstring(key , LPHM);//hash
for( ; Heads[i].key != NULL ; i = (i + 1)%LPHM)//循环查找
if(strcmp(Heads[i].key , key) == 0){//遍历命中则更新
Heads[i].val = val;
return ;
}
Heads[i].key = key;//未命中,则插入空白位置
Heads[i].val = val;
LPHCount++;//元素加1
}
Value LinearProbingHashST_Get(Key* key )
{
int i = hashstring(key , LPHM);
for( ; Heads[i].key != NULL ; i = (i + 1)%LPHM)//循环查找
if(strcmp(Heads[i].key , key) == 0){//遍历命中则返回
return Heads[i].val;
}
return 0;//遇到空未命中,返回空
}
void LinearProbingHashST_Delete(Key* key )
{
int i;
struct LPHashnode temp;
if(key == NULL)//key为空,直接返回
return ;
i = hashstring(key , LPHM);
while(Heads[i].key != NULL){//查找键直到遇到空为止(如果遇到空,那么肯定键不在表中)
if(strcmp(Heads[i].key , key) == 0)
break;
else
i = (i+1)%LPHM;
}
if(Heads[i].key == NULL)//遇到空,证明不在表中
return ;
Heads[i].key = NULL;//命中,则键清空
Heads[i].val = 0;
i = (i+1)%LPHM;//索引键簇下一个元素
while(Heads[i].key != NULL){//将键重新插入表
temp = Heads[i];//缓存键值
Heads[i].key = NULL;//将键清空
Heads[i].val = 0;
LPHCount--;
LinearProbingHashST_Put(temp.key , temp.val);//并重新插入
i = (i+1)%LPHM;
}
LPHCount--;//总体元素个数减1
if(LPHCount > 0&&LPHCount == LPHM / 8){//如果总体元素太少,为了节约空间,缩小LPHM
LPHM = LPHM/2;
ReSize_LPHM(LPHM);//消耗时间
}
}
int LinearProbingHashST_Size()
{
return LPHCount;
}
/************************************************************/
一键复制
编辑
Web IDE
原始数据
按行查看
历史