数据结构--散列(使用开放定址法解决冲突)

     前一篇博客中提到解决散列冲突的方法为分离链接法,它的装填因子为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;
}

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

 

     夜深了,,,

 

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

posted on 2017-05-05 21:56  wu_xin  阅读(895)  评论(0编辑  收藏  举报

导航