前一篇博客中提到解决散列冲突的方法为分离链接法,它的装填因子为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; }
这些数据结构的思想都值得我们借鉴。
夜深了,,,
我们都是方鸿渐,不讨人厌,但也全无用。