您的位置:首页 > 其它

哈希工作原理与应用

2016-05-27 09:40 423 查看
参考

/article/8617172.html

基本原理

我们使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一 个元素“分类”,然后将这个元素存储在相应“类”所对应的地方。

但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”之中。后面我们将看到一种解决“冲突”的简便做法。

总的来说,“直接定址”与“解决冲突”是哈希表的两大特点。

函数构造

构造函数的常用方法(下面为了叙述简洁,设 h(k) 表示关键字为 k 的元素所对应的函数值):

a) 除余法:

选择一个适当的正整数 p ,令 h(k ) = k mod p ,这里, p 如果选取的是比较大的素数,效果比较好。而且此法非常容易实现,因此是最常用的方法。

b) 数字选择法:

如果关键字的位数比较多,超过长整型范围而无法直接运算,可以选择其中数字分布比较均匀的若干位,所组成的新的值作为关键字或者直接作为函数值。

冲突处理

线性重新散列技术易于实现且可以较好的达到目的。令数组元素个数为 S ,则当 h(k) 已经存储了元素的时候,依次探查 (h(k)+i) mod S , i=1,2,3…… ,直到找到空的存储单元为止(或者从头到尾扫描一圈仍未发现空单元,这就是哈希表已经满了,发生了错误。当然这是可以通过扩大数组范围避免的)。

哈希算法应用

查找一个数组中是否有相同值

代码

bool containsDuplicate(vector<int>& nums) {
bool bRes=false;
if(nums.size()==0) return bRes;

int len=nums.size();
bool *hashIsStore=new bool[len];
int *hashTable=new int[len];
memset(hashIsStore,0,len);
memset(hashTable,0,len);

for(int i=0;i<len;i++)
{
int assign=nums[i]%len;

int n=0;
int locate=(assign+n)%len;
while(locate<0||(hashIsStore[locate]&&hashTable[locate]!=nums[i])  )
{
n++;
locate=(assign+n)%len;
}

if(hashIsStore[locate])
{
bRes=true;
break;
}
else
{
hashIsStore[locate]=true;
hashTable[locate]=nums[i];
}

}

delete [] hashTable;
delete [] hashIsStore;

return bRes;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: