哈希表的简单实现

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值,进行判断。

 

 

 

posted @ 2013-04-08 11:02  李VS超  阅读(423)  评论(0编辑  收藏  举报