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; 因为参数 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 |
和二叉查找树类似,哈希表作为动态查找表的一种组织方法,建表的过程也是从空表起,逐个插入记录的过程。左侧为在开放定址的哈希表中插入记录的算法。 有时也可能因为哈希函数不够好,以至当表中记录数较多时冲突次数大大增加,可在插入算法中设立一个冲突次数的上限,一旦冲突次数超过该上限,可重新构建哈希表。 链地址处理冲突的哈希表的查找和插入算法则更简单。 |