浅谈哈希函数与线性探测再散列

        我们知道,一般很多网页的URl地址都是巨长无比的,那么要存储每个网页真的需要为它们分配如此冗长的空间吗,我们相信这些足以让服务器崩溃的愚蠢行为是不会被各大互联网巨头所采用的,所以,他们会选择采用哈希函数的方式来存储这些地址。

        对于一般的线性表,树中,记录在结构中的相对位置是随机的,即和记录的关键字之间不存在确定的关系,因此,在结构中查找记录时需进行一系列和关键字的比较。这一类查找方法建立在“比较“的基础上,查找的效率依赖于查找过程中所进行的比较次数。 理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。

        而哈希表中元素是由哈希函数确定的。将数据元素的关键字K作为自变量,通过一定的函数关系(称为哈希函数),计算出的值,即为该元素的存储地址,表示为:Addr = H(key)。

        哈希函数的好坏在与其对于冲突的处理的好坏。在哈希表中,不同的关键字值对应到同一个存储位置的现象。即关键字K1≠K2,但H(K1)=H(K2)。均匀的哈希函数可以减少冲突,但不能避免冲突。发生冲突后,必须解决;也即必须寻找下一个可用地址。

        要处理这种冲突,我们可以采用如下的方式:

1.拉链法

  拉出一个动态链表代替静态顺序存储结构,可以避免哈希函数的冲突,不过缺点就是链表的设计过于麻烦,增加了编程复杂度。此法可以完全避免哈希函数的冲突。

2.多哈希法

   设计二种甚至多种哈希函数,可以避免冲突,但是冲突几率还是有的,函数设计的越好或越多都可以将几率降到最低(除非人品太差,否则几乎不可能冲突)。

3.开放地址法

  开放地址法有一个公式:Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)
  其中,m为哈希表的表长。di 是产生冲突的时候的增量序列。如果di值可能为1,2,3,...m-1,称线性探测再散列。
  如果di取1,则每次冲突之后,向后移动1个位置.如果di取值可能为1,-1,2,-2,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2)
  称二次探测再散列。如果di取值可能为伪随机数列。称伪随机探测再散列。

4.建域法

   假设哈希函数的值域为[0,m-1],则设向量HashTable[0..m-1]为基本表,另外设立存储空间向量OverTable[0..v]用以存储发生冲突的记录。


下面我们来看一个简单的哈希函数的例子,本例采用的是P.J.Weinberger的哈希算法:

// P. J. Weinberger Hash 
unsigned int PJWHash(char *str)
{
    unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);
    unsigned int ThreeQuarters    = (unsigned int)((BitsInUnignedInt  * 3) / 4);
    unsigned int OneEighth = (unsigned int)(BitsInUnignedInt / 8);
    unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnignedInt 
                                               - OneEighth);
    unsigned int hash    = 0;
    unsigned int test    = 0;
 
    while (*str)
    {
        hash = (hash << OneEighth) + (*str++);
        if ((test = hash & HighBits) != 0)
        {
            hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
        }
    }
 
    return (hash & 0x7FFFFFFF);
}  

        相信看了上面的程序,许多人都会说,这是什么垃圾算法啊,这个莫名奇妙。的确,在哈希函数中,这是一个效率不太高的算法,对于有效的散列数据的存储不是靠复杂的地址分配就可以完成的,所以,要想真正的完成一个适合于自己的文件存储的哈希函数,绝不能一概而论。

        写到这这篇文章也就差不多了,也许你会说为什么没有提到什么是线性探测再散列,我想说的是,对于那些学了哈希函数却只知道用线性探测再散列这个装B的概念来显示自己高端的人,您还是回家洗洗睡吧。真正高明的哈希函数可不是用线性探测再散列就可以解决的,这种东西最多也只会在各种无趣的等级考试中出现了。

        顺便鄙视下某企鹅今年的校园招聘出了个线性探测再散列的题目。好了,写到这也差不多了,最为一篇浅谈性质的文章,我也不想讲的太多了,所以就这样吧!




已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页