最简单的哈希表删除元素

有一个简单的Hash表,采用一位数组直接存放元素,Hash函数是个对表长取模,冲突解决采用线性探测。

这样的Hash表较容易实现,查找和插入方法都按照先哈希再探测的步骤就可以了,但删除表中的元素稍微复杂。

 

因为表中有冲突的元素存在,这些元素应用了探测方法被放置在其他位置上,若删除表中一个元素可能对这些元素的查找造成影响,可能使查找元素的正常过程中断。这里称由于删除一个元素给哈希表造成一个gap。我们称关键字key的哈希值为key的哈希位置;称使用探测技术重新安排位置的元素为后置元素。

 

为了避免事情的发生,我们需要fill in gaps直到所有的元素都能被找到。下面是一段简单的代码。

 

//假设哈希表Hash中存放结构体student的相关信息,使用学号id作为关键字.

//称学号为id的元素为元素id。id==0表示该哈希表项未被占用。

 

int find(int id);//返回元素id在表中的位置

int hash(int id);//计算元素id的哈希值

 

void delete(int id){

       int i=find(id);

       for(;;){                  

              Hash(i).id = 0;  //删除元素i,产生一个gap。

              int j=i; //j存放gap的位置,下面要从gap后面选出一个后置元素来填充gap。

              for(;;){                                      //这里选择离gap最近的那个

              i= (++i)%Hash_Table_Size;  

              if(Hash(i).id == 0){                   //遇到了未用的slot,因从gap到该slot段的后置元素都被处理得当,不会再有新的gap产生

                     return;                              //所以方法可以结束了。

              }

              int r=hash(i);                          //若当前元素的哈希位置r位于gap和其当前位置i之间,则不选择该元素。

              if(j

                     continue;                        //三个if语句考虑到了i,j的位置关系,即i,j的大小。三个条件都限制了r要在i和j之间。

              if(j>i && j

                     continue;

              if(j>i && r<=i)

                     continue;                         

              break;                                     ///元素的哈希位置在允许的范围之外,即它为受影响的后置元素。则:                        

              }//for                                     

              Hash(j)=Hash(i);                     //选择该元素填充gap。并删除该元素产生一个新gap       

       }//for 

}//delete

 

这只是一种最为简单的Hash表实现。为避免这样删除的麻烦,可以采用链表法或设置公共溢出区来解决冲突。

 

有两篇不错的文章:

哈希表的一个实现:http://hi.baidu.com/wihate/blog/item/e0330b7a7a2e9fee2e73b3ae.html

c++实现的一个哈希表类:http://hi.baidu.com/wihate/blog/item/d537ba01070352d5277fb5dc.html

 

希望以后继续学习哈希表。

 

你可能感兴趣的:(算法与数据结构)