9.4.4 开放定址的哈希表的查找和插入

  在利用开放定址处理冲突的哈希表中进行查找时,首先应计算给定值的哈希函数值,若表中该位置上没有记录,则表明关键字等于给定值的记录不存在;若该位置上的记录的关键字和给定值不等,则依据建表时设定的增量值寻找"下一个"地址,直至查找成功(即某个位置上的记录的关键字等于给定值)或查找不成功(哈希表中不存在关键字等于给定值的记录),并且在查找不成功的情况下,该地址恰为新的记录的插入位置。其算法如下:

算法 算法 9.8
  Status SearchHash (HashTable H, KeyType kval, int &p, int &c)
 {
  // 在开放定址哈希表H中查找关键码为kval的元素,若查找成功,以p指
  // 示待查记录在表中位置,并返回SUCCESS;否则,以p指示插入位置,并
  // 返回UNSUCCESS,c 用以计冲突次数,其初值置零,供建表插入时参考

  p = Hash(kval);           // 求得哈希地址
  while ( H.elem[p].key != NULLKEY   // 该位置中填有记录
      && ( H.elem[p].key != kval) ) // 并且关键字不相等
   collision(p, ++c);         // 求得下一探查地址p
  if ( H.elem[p].key == kval )
   return SUCCESS;         // 查找成功,p 返回待查记录位置
  else return UNSUCCESS;
      // 查找不成功(H.elem[p].key == NULLKEY),p返回的是插入位置
 } // SearchHash
 
   
 
 
算法 开放定址哈希表的存储结构
 int hashsize[ ] = { 997, ... };
  // 哈希表容量递增表,一个合适的素数序列
 typedef struct
{
 ElemType *elem; // 记录存储基址,动态分配数组
 int count;   // 当前表中含有的记录个数
 int sizeindex;
    // hashsize[sizeindex]为当前哈希表的容量
} HashTable;

 const SUCCESS = 1;
 const UNSUCCESS = 0;
 const DUPLICATE = -1;

  因为参数 c 的初值为0,则查找结束时,c 的值即为产生冲突的次数。

 
  算法 算法 9.9
  Status InsertHash (HashTable &H, Elemtype e)
 {
  // 若开放定址哈希表H中不存在记录 e 时则进行插入,并返回OK;
  // 若在查找过程中发现冲突次数过大,则需重建哈希表

  c = 0;
  if ( HashSearch ( H, e.key, j, c ) == SUCCESS )
   return DUPLICATE;     // 表中已有与 e 有相同关键字的记录
  else if ( c < hashsize[H.sizeindex]/2 ) {
                 // 冲突次数c未达到上限,(阀值c可调)
   H.elem[j] = e; ++H.count; return OK; // 插入记录 e
  } // if
  else RecreateHashTable(H);  // 重建哈希表
 } // InsertHash
   
  和二叉查找树类似,哈希表作为动态查找表的一种组织方法,建表的过程也是从空表起,逐个插入记录的过程。左侧为在开放定址的哈希表中插入记录的算法。
 
  有时也可能因为哈希函数不够好,以至当表中记录数较多时冲突次数大大增加,可在插入算法中设立一个冲突次数的上限,一旦冲突次数超过该上限,可重新构建哈希表。
 
  链地址处理冲突的哈希表的查找和插入算法则更简单。