zoukankan      html  css  js  c++  java
  • 数据结构--散列(使用开放定址法解决冲突)

         前一篇博客中提到解决散列冲突的方法为分离链接法,它的装填因子为1,每次插入一个元素就申请一个空间,但是,开放定址不一样,  所谓的开放定址就是散列一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入,具体寻找空地址的方法有线性探测法,平方探测法,双散列等等,注意,对于开放定址来说,装填因子应该小于0.5.

         使用平方探测解决冲突,代码如下:

        

    #include<iostream>
    
    using namespace std;
    
    #define MinTablesize 10
    typedef unsigned int Index;
    typedef Index Position;
    
    struct Hashtal;
    typedef struct Hashtal *Hashtable;
    
    enum KindOfEntry  //枚举类型,只能是其中的一个值
    {
      Legitimate,Empty,Delete
    };
    
    struct HashEntry
    {
       int Element;
       enum KindOfEntry Info;
    };
    
    typedef struct HashEntry Cell;
    
    struct Hashtal
    {
      int TableSize;
      Cell *Thecells;
    };
    
    int Hash (int x,Hashtable H)   //散列函数
    {
       return x % H->TableSize;
    }
    
    int NextPrime (int Key)  // 寻找Key后的第一个素数
    {
    	if(Key == 1 || Key == 2)
    		return Key;
    
        bool flag = 0;
    	int pre_Key;
    	while(!flag)
    	{
    	   pre_Key = Key;
    	   for(int i = 2; i != Key; ++i)
    	   {
    	      if(Key % i == 0)   //Key不是素数
    		  {
    		     Key++;
    			 break;
    		  }
    		  
    	   }
    	   if(pre_Key == Key)  //说明Key没有改变
    		   flag = 1;
    	   else
    		   flag = 0;
    
    	}
    	return Key;
    }
    Hashtable InitTable(int Tablesize)
    {
       Hashtable H;
       if(Tablesize < MinTablesize)
       {
         cout << "Table is too small" << endl;
    	 return NULL;
       }
    
       //创建散列表
       H = (Hashtable)malloc(sizeof(struct Hashtal));
       if(H == NULL)  cout << "out of space " << endl;
       H->TableSize = NextPrime(Tablesize);  //大小为Tablesize后的第一个素数
       H->Thecells = (Cell*)malloc(sizeof(Cell) * H->TableSize );
       if(H->Thecells == NULL)  cout << "out of space " << endl;
       for (int i = 0; i != H->TableSize; ++i)
          H->Thecells[i].Info = Empty;   //每个元素都标记为空
       return H; 
    }
    
    Position Find (int Key , Hashtable H)
    {
       Position CurrPos;
       int CollNum;
       CollNum = 0;
       CurrPos = Hash(Key,H);
       while(H->Thecells[CurrPos].Info != Empty && H->Thecells[CurrPos].Element != Key)  //找不到时返回一个空单元
       {
          CurrPos += 2 * (++CollNum) - 1;    //使用平方探测散列法
    	  if(CurrPos >= H->TableSize )
    		  CurrPos -= H->TableSize;
       }
       return CurrPos;
    }
    
    void Insert(int Key,Hashtable H)
    {
      Position Pos;
      Pos = Find(Key,H); //看找不找的到,找到就算了,找不到就插入
      if(H->Thecells[Pos].Info != Legitimate)  //
      {
         H->Thecells[Pos].Element  = Key;
    	 H->Thecells[Pos].Info = Legitimate;
      }
    }
    
    Hashtable Rehash (Hashtable H)   //再散列,把表的大小放大到原来的2倍,再把原来的元素插入到新散列表中
    {
    	int Oldsize;
    	Cell *Oldcells;
    
    	Oldcells = H->Thecells;
    	Oldsize = H->TableSize;
    
    	H = InitTable(2 * Oldsize);
    
    	for (int i = 0; i != Oldsize; ++i)
    	{
    	  if(Oldcells[i].Info == Legitimate)
    		  Insert(Oldcells[i].Element, H);
    	}
    	free(Oldcells);
    	return H;
    }
    
    int main ()
    {
    	Hashtable H = InitTable(10);
    	
    	Insert(10,H);
    
    	cout << H->Thecells [Find(10,H)].Element << endl;
    
       return 0;
    }
    

      这些数据结构的思想都值得我们借鉴。

         夜深了,,,

      我们都是方鸿渐,不讨人厌,但也全无用。

  • 相关阅读:
    [Tips] 树莓派VNC登录
    [Tips] 联通宽带+华为路由器,如何进行NAT
    [Tips] 树莓派4B 风扇安装
    [Tips] 家庭树莓派,如何外网访问
    [Tips] 命令行获取设备的外网IP
    MySQL 如何让自增id设置为从1开始
    MySQL报错:Packet for query is too large (2,588 > 2,048).
    Java 实现 Timstamp 和 String 互相转换
    MySQL修改 mysql-bin 日志保存天数以及文件大小限制
    Linux Shell 中的年月日 时分秒
  • 原文地址:https://www.cnblogs.com/1242118789lr/p/6815076.html
Copyright © 2011-2022 走看看