动态hash之linear Hash的实现和性能比较

本文介绍了动态hash中的线性Hash,对比静态hash,线性Hash能动态调整bucket数量以维持查找效率。文章详细阐述了线性Hash的insert、find和erase操作,并与STL的map及hash_map进行了性能比较。测试结果显示线性Hash在插入和查找上表现优秀。
 

linear hash

 

一,在介绍linear hash 之前,需要对动态hash和静态hash这两个概念做一下解释:

 

静态hash:是指在hashtable初始化得时候bucket的数目就已经确定了,当需要插入一个元素的时候,通过hash函数找到对应的bucket number,之后插入即可。不论用什么冲突解决方法,当插入的元素越来越多时,在这个hash表中查找元素的效率会变的越来越低。

动态hash:是指在hashtable的bucket的数目不是确定的,而是会根据插入元素的多少而实现动态的增减,当元素变多得时候,bucket会动态增加,这样就可以解决静态hash的查找效率低得问题。当元素变少得时候,bucket会动态减少,从而减少空间的浪费。linear hash就是一种动态hash。

 

二。linear hash实现.

对于hash操作,主要有insert, find, erase三个操作,下面对linear_hash的3个操作做一些解析:

1.       Find.

对于查找操作,目的是输入key值,找出对应的卫星数据的值,这一操作和其他hash操作一样。

bool find(KeyType iKey, DataType& oData)

                   {

                            int lKey = hashfunc(iKey);

 

                            if(lKey < 0 || lKey >= numBucket) return false;

                            bucketIter iter = mhashTable[lKey].begin();

                            for(; iter != mhashTable[lKey].end(); iter ++)

                            {

                                     if(iter->first == iKey)

                                     {

                                               oData = iter->second;

                                               return true;

                                     }

                            }

 

                            return false;

                   }


 

2.       Insert操作。

对于插入操作,客户端程序输入key值和卫星数据,进行这一操作,会增加Linearhash中的元素个数numElement,当Linearhash的bucket负载(numElements/numBuckets)超过一定值,需要动态的增加Bucket数,增加一个bucket, 接着需要把一个特定的bucket上的element分一部分到这个new 的bucket上。

 

bool insert(KeyType iKey, DataType& iData)

                   {

                            int lKey = hashfunc(iKey);                           

                            if(lKey < 0 || lKey >= numBucket) return false;

 

                            //把这个element插入到对应的bucket(mHashTable[lKey])里面

                            mhashTable[lKey].push_back(make_pair(iKey, iData));

                            numElement ++;

 

                            //计算现在Container的负载= 现在的元素个数/bucket数目

                            double loadFctr = (double)numElement / numBucket;

                            //如果负载操作最大的负载数,那么需要做extend操作。

                            //目的是增加bucket数,接着均分bucket上得element

                            if(loadFctr >= maxloadfctr)

                            {

                                     Extend();

                            }

                            return true;

                   }

 

 void Extend()

                     {

                            //计算出需要被均分的bucket位置mhashTable[oldPos].

                            //计算出新的bucket位置mhashTable[newPos].

                              int oldpos = p;

                              int newpos = numBucket;

                              mhashTable.resize(++ numBucket);

                              

              //接着调整Container的状态,

                            //当p增加到最大的maxp的值时,需要成倍的增加maxp数,同时p回归为0

                              p = p + 1;

                              if(p == maxp)

                              {

                                       maxp *= 2;

                                       p = 0;

                              }

                             

                            //接下来把mhashtable[oldpos]这个bucket中的元素按照一定的规则分配到nhashTable[newPos]内,一部分会留在原来的mhashtable[oldpos]中

                              bucketIter iter = mhashTable[oldpos].begin();

                              for(; iter != mhashTable[oldpos].end(); )

                              {

                                       if(hashfunc(iter->first) == newpos)

                                       {

                                                 mhashTable[newpos].push_back(make_pair(iter->first, iter->second));

                                                 iter = mhashTable[oldpos].erase(iter);

                                       }

                                       else

                                                 iter ++;

                                       

                              }

 

                     }


3.       Erase操作

对于erase操作,客户端程序给定key值,要求contianer删除其中和key值相同的元素。同时需要减少numElement数,当Linearhash的bucket负载(numElements/numBuckets)减少到一定值,需要动态的减少Bucket数,减少一个bucket, 同时需要把这个减少的bucket中的所有元素还原到原来的oldBucket中。

bool erase(KeyType iKey)

                   {

                            int lKey = hashfunc(iKey);

                            if(lKey < 0 || lKey >= numBucket) return false;

                            bool isfound = false;

                            //在mhashTable[lKey]这个bucket中查找这个lKey值

bucketIter iter = mhashTable[lKey].begin();

                            for(; iter != mhashTable[lKey].end(); )

                            {

                                     if(iter->first == iKey)

                                     {

                                               iter = mhashTable[lKey].erase(iter);

                                               isfound = true;

                                               break;

                                     }

                                     else

                                     {

                                               iter ++;

                                     }

                            }

                            

                            //如果找到了,需要减少numElement值,调增bucekt数

                            if(isfound)

                            {

                                     numElement --;

                                     double loadFctr = (double)numElement / numBucket;

                                     if(loadFctr <= minloadfctr && numBucket > FIRSTBUCKETS)

                                     {

                                               Shrink();

                                     }

                                     return true;

 

                            }

 

                            return false;

                   }

void Shrink()

                     {

                            //调增状态

                             p--;

                             if(p < 0)

                             {

                                      maxp /= 2;

                                      p = maxp -1;

                             }

                            

                            //把mhashtable[numBucekt-1]中的元素全部insert到mhashtable[p]这个bucket中,

                            //同时调增mhashtable的大小。

                             mhashTable[p].insert(mhashTable[p].end(), mhashTable[numBucket-1].begin(), mhashTable[numBucket-1].end());

                             mhashTable[numBucket - 1].clear();

                             mhashTable.resize(--numBucket);

 

                     }

 


 

三.于STL::map和STLEXT::hash_map做了一下性能比较。

 


测试结果如下:

Linearhash insert time consume: 160

Linearhash find time consume: 50

Linearhash erase time consume: 70

map insert time consume: 80

map find time consume: 40

map erase time consume: 110

hash_map insert time consume: 150

hash_map find time consume: 40

hash_map erase time consume: 2130

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值