zoukankan      html  css  js  c++  java
  • 哈希表的简单实现

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

  • 相关阅读:
    jquery实现回车键执行ajax
    php post请求
    题解 P2825 【[HEOI2016/TJOI2016]游戏】
    莫队
    一些关于数学的知识(总结)
    P3232[HNOI2013]游走
    万物生长 / Tribles
    [BZOJ4244]邮戳拉力赛
    P1095 守望者的逃离
    P3953 逛公园
  • 原文地址:https://www.cnblogs.com/fistao/p/3006974.html
Copyright © 2011-2022 走看看