哈希表

来源:互联网 发布:局域网网络限速软件 编辑:程序博客网 时间:2024/06/07 13:52

1.哈希表也叫散列表

一种O(1)的查找,即所谓的秒杀。所谓哈希关系,即哈希函数,就是一个key对应一个value,要遵循的原则:

 ①:  key尽可能的分散。也就是丢一个“6”和“5”,都返回一个“2”,那么这样的哈希函数不尽完美。

 ②: 哈希函数尽可能的简单。也就是说丢一个“6”给你,你哈希函数要搞1小时才能给我,这样也是不好的。


2.常用的做哈希的手法有“五种”:

第一种:”直接定址法“。

                  很容易理解,key=Value+C; 这个“C"是常量。Value+C其实就是一个简单的哈希函数。

第二种:“除法取余法”。

                  很容易理解, key=value%C;解释同上。

第三种:“数字分析法”。

                  这种蛮有意思,比如有一组value1=112233,value2=112633,value3=119033,

                  针对这样的数我们分析数中间两个数比较波动,其他数不变。那么我们取key的值就可以是

                  key1=22,key2=26,key3=90。 

第四种:“平方取中法”。此处忽略,见名识意。

第五种:“折叠法”。

                 这种蛮有意思,比如value=135790,要求key是2位数的散列值。那么我们将value变为13+57+90=160,

                 然后去掉高位“1”,此时key=60,哈哈,这就是他们的哈希关系,这样做的目的就是key与每一位value都相

                 关,来做到“散列地址”尽可能分散的目地。

 

正所谓常在河边走,哪有不湿鞋。哈希也一样,你哈希函数设计的再好,搞不好哪一次就撞楼了,那么抛给我们的问题

就是如果来解决“散列地址“的冲突。

 

3.其实解决冲突常用的手法也就2种:

 

第一种: “开放地址法“。

                 所谓”开放地址“,其实就是数组中未使用的地址。也就是说,在发生冲突的地方,后到的那个元素(可采用两种方式

                 :①线性探测,②函数探测)向数组后寻找"开放地址“然后把自己插进入。

 

第二种:”链接法“。也叫拉链法

                这个大家暂时不懂也没关系,我就先介绍一下原理,就是在每个元素上放一个”指针域“,在发生冲突的地方,后到的那

               个元素将自己的数据域抛给冲突中的元素,此时冲突的地方就形成了一个链表。


4.【应用举例】

海量处理

给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?

答:

可以估计每个文件安的大小为5G×64=320G,远远大于内存限制的4G。所以不可能将其完全加载到内存中处理。考虑采取分而治之的方法。

 分而治之/hash映射

遍历文件a,对每个url求取,然后根据所取得的值将url分别存储到1000个小文件(记为,这里漏写个了a1)中。这样每个小文件的大约为300M。遍历文件b,采取和a相同的方式将url分别存储到1000小文件中(记为)。这样处理后,所有可能相同的url都在对应的小文件()中,不对应的小文件不可能有相同的url。然后我们只要求出1000对小文件中相同的url即可。

 hash_set统计

求每对小文件中相同的url时,可以把其中一个小文件的url存储到hash_set中。然后遍历另一个小文件的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。

 

(此题来源于v_July_v的博客)

 

//创建哈希表,初始化哈希表const int tablesize = 256;unsigned int hashTable[tablesize];for(unsigned int i = 0;i < tablesize; ++i)hashTable[i] = 0;




0 0