哈希表的简单实现
HashTable算法概要:
哈希表示表示集合和字典的另外一种有效的方法,通过将关键码映射到表中
某个位置来存储元素,然后根据关键码用同样的方式直接访问。
1、有限的连续地址,可以用数组来表示。
2、Hash函数采用除留余数法。
3、处理冲突的方法,用开放地址法,实现线性探测再散列法,
二次探测再散列法,随即探测再散列法,后两种方法有一些对条件的限制。
4、给定一系列的键值,分配一个数组,用哈希函数处理地址,在哈希函数中调用
冲突处理函数。
5、查找函数。
哈希表的类定义代码如下:
class HashT{
public:
HashT(){} //构造函数
~HashT(){} //析构函数
//哈希函数
void HashLFun(int key[],int keysize,int dest[],int destsize,int mod); //哈希函数,算法采用除留余数法
void HashQFun(int key[],int keysize,int dest[],int destsize,int mod); //哈希函数,算法采用除留余数法
//处理冲突函数
int HashLinearPro(int H0,int i,int mod); //线性探测再散列法
int HashQuadraticPro(int me,int H0,int mod,int flag); //二次探测再散列法
};
哈希函数根据处理冲突的方法不同,分为两个。
哈希函数(除留余数法)算法:采用线性探查再散列法
1、传入键值数组、模值和目标数组。
2、要处理一批键值,所以应该使用一个循环。
3、采用除留余数法求第一次的地址值。
4、判断是否产生了冲突,如果产生冲突,就调用冲突处理函数,寻找下一个可用的地址。
算法代码如下:
void HashT::HashLFun(int key[],int keysize,int dest[],int destsize,int mod)
{
int destnum;
for(int i=0;i<keysize;i++) //处理这个键值序列
{
destnum=key[i]%mod;
int fuben=destnum; //记录当前值,用于循环
if(dest[destnum]==0)
{
//如果该数组值等于0,说明没有发生冲突,则将该键值插入到该数组
dest[destnum]=key[i];
}
else
{
int count=i; //保存i的值,不改变原程序中i的值
//否则发生了冲突,调用冲突处理函数,将key值赋值给下一个合适的位置
while(dest[destnum]!=0) //如果冲突,继续循环处理
{
destnum=HashLinearPro(destnum,count,mod);
if(destnum!=fuben) //如果i值小于总的大小,就继续增加探测
count++;
else
cout<<"表中不存在可以存储该键值的位置"<<endl;
}
//while循环之后,说明找到了这个位置
dest[destnum]=key[i];
}
}
}
采用二次探查法解决冲突的算法代码如下:
void HashT::HashQFun(int key[],int keysize,int dest[],int destsize,int mod)
{
int destnum;
for(int i=0;i<keysize;i++) //处理这个键值序列
{
destnum=key[i]%mod;
int fuben=destnum;
if(dest[destnum]==0)
{
//如果该数组值等于0,说明没有发生冲突,则将该键值插入到该数组
dest[destnum]=key[i];
}
else
{
int count=1;
int flag=0; //设定一个调用次数的标记
//否则发生了冲突,调用冲突处理函数,将key值赋值给下一个合适的位置
while(dest[destnum]!=0) //如果冲突,继续循环处理
{
flag++; //调用次数加1
destnum=HashQuadraticPro(count,destnum,mod,flag);
//if(count<destsize) //如果i值小于总的大小,就继续增加探测
//count++; //这个地方不严谨,应该可以回到最初的位置
//else
//cout<<"表中不存在可以存储该键值的位置"<<endl;
if(flag%2==0){
//如果循环若干次后又回到原来的位置,说明没有可插入的位置
count++;
}
else if(destnum==fuben)
{
cout<<key[i]<<"在表中没有合适的插入位置"<<endl;
}
else
; //否则什么都不做
}
//while循环之后,说明找到了这个位置
dest[destnum]=key[i];
}
}
}
哈希函数中很重要的一个部分就是冲突处理函数,这里写出最常用的两个处理方法,线性探查再散列法和二次探查再散列法:
算法的代码如下:
int HashT::HashLinearPro(int H0,int i,int mod)
{
int destnum;
destnum=(H0+i)%mod;
return destnum;
}
int HashT::HashQuadraticPro(int me,int H0,int mod,int flag)
{
int destnum;
if(flag%2==1)
{
destnum=(H0+me*me)%mod; //这里的i应该为me
}
else
{
destnum=(H0-me*me)%mod;
}
return destnum;
}
二次探查再散列法,需要设置征服号,这里设置一个flag值,进行判断。

浙公网安备 33010602011771号