随笔64 hash表

1、哈希函数进行模除取余时,最好取素数进行模除。

【解析】哈希表设计目的就是希望尽量的随机散射不希望这些在同一列上的元素(也就是会冲突的元素)之间具有关系,所以我们都采用素数作为哈希表的大小,从而避免模数相同的数之间具备公共因数

① 如果用一个合数8作为哈希表大小,0-30在哈希表中的散射情况:

② 用质数7作为哈希表大小,0-30在哈希表中的散射情况:

2、哈希表装填因子(负载因子)定义为:α= 填入表中的元素个数 / 哈希表的长度

α是哈希表装满程度的标志因子。由于表长是定值,α与“填入表中的元素个数”成正比,所以,α越大,填入表中的元素较多,产生冲突的可能性就越大;α越小,填入表中的元素较少,产生冲突的可能性就越小。

3、哈希函数构造主要有以下几种:

  • 1:直接寻址法;
  • 2:取模法;
  • 3:数字分析法;
  • 4:折叠法;
  • 5:平方取中法;
  • 6:除留余数法;
  • 7:随机数法。

4、Hash处理冲突的方法

开放地址法:在得到Hash值后如果产生冲突,则加一个增量d,直至没有冲突的位置。

  d的取法:

  (1)线性探测再散列:1,2,3,4... 其实就是当发生冲突时,从该冲突位置逐个向后查找,类似于循环数组,直到找到合适的位置或者找遍整个表都未找到合适的位置。这个方法的缺点是易发生堆聚现象,堆聚就是存入哈希表的数据在表中连成一片

  【注】哈希查找中k个关键字具有同一哈希值,若用线性探测法将这k个关键字对应的记录存入哈希表中,至少要进行(k ( k + 1 ) / 2)次探测。--- 第一次算线性探测

  【注】设有n个关键字具有相同的Hash函数值,则用线性探测法把这n个关键字映射到Hash表中需要做 n * (n - 1) / 2 次线性探测? --- 第一次不算线性探测

    第一个关键字直接插入,第二个关键字要做1次探测,所以类推n个关键词要做0+1+2+...+(n-1) = n * (n - 1) / 2 。

  (2)二次探测再散列(平方探测法):可以避免堆积问题。

  

【例题】设哈希表长为14,哈希函数是H(key)=key%11,表中已有数据的关键字为15,38,61,84共四个,现要将关键字为49的结点加到表中,用二次探测再散列法解决冲突,则放入的位置是( 9 )。

【解析】15%11 = 4,38%11 = 5,61%11 = 6,84%11 = 7.

要求49的位置:49%11 = 5,被占用了,使用二次探测再散列法,<1> (5+1^2)%14=6   冲突  <2> (5-1^2)%14=4  冲突 <3>  (5+2^2)%14=9  不冲突,得到最终位置为9.

  (3) 伪随机探测再散列。将步长改为随机数,这样使不同的关键字具有不同的探测顺序,可以有效避免堆聚。

再哈希表法:产生冲突时取不同的哈希函数计算,但缺点是不易产生“聚集”,增加计算时间

链地址法:拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短

【例题】设散列表的长度为8,散列函数H(k)=k mod 7,初始记录关键字序列为(32,24,15,27,20,13),计算用链地址法作为解决冲突方法的平均查找长度是(1.5)

【解析】链地址法作为解决冲突 方法:将所有关键字为同义词的记录存储在一个单链表中,并用一维数组存放头指针

0  1  2   3   4  5  6

15     24 32     27

20

13

因此查找长度为 1、 1、 1、1、 2、3 等概率情况下查找成功时的平均查找长度为 9 / 6 = 1.5。

④ 建立一个公共溢出区

5、Hash操作能根据散列值直接定位数据的存储地址,设计良好的hash表能在常数级时间下找到需要的数据,但是更适合于内存中的查找

B+树是一种是一种树状的数据结构,适合做索引,对磁盘数据来说,索引查找是比较高效的

STL_Map的内部实现是一颗红黑树,但是只是一颗在内存中建立二叉树不能用于磁盘操作,而其内存查找性能也比不上Hash查找。

因此三者中,对于内存中数据,查找性能较好的数据结构是Hash_Map,对于磁盘中数据,查找性能较好的数据结构是B+Tree

6、设哈希表长度为11,哈希函数H(K)=(K的第一个字母在字母表中的序号) MOD 11,若输入顺序为(D,BA,TN,M,CI,I,K,X,TA),采用内散列表,处理冲突方法为线性

测法,要求构造哈希表,在等概率情况下查找成功平均查找长度为:20/9 。

【解析】


散列表


0


1


2


3


4


5


6


7


8


9


10


散列元素


K


TN


BA


M


D


CI


X


TA


I


查找成功次数


1


4


1


2


1


3


5


1


2


查找失败次数


7


6


5


4


3


2


1


1


1


9


8

平均查找成功长度跟平均查找失败长度如下:

ASL suc =(1+4+1+2+1+3+5+1+2)/ 9 = 20 / 9

ASL fail =(7+6+5+4+3+2+1+1+1+9+8)/11 = 47 / 11

D=4mode11=4,1次  B=2mod11=2,1次  T=20mod11=9,1次  M=13mod11=2->3,2次  C=3mod11=3->4->5,3次  I=9mod11=9->10,2次

K=11mod11=0,1次  X=24mod11=2->3->4->5->6,5次  T=20mod11=9->10->0->1,4次

9个数字,共20次,所以20/9。

某个(哈希表中并不存在的)值n对11取余之后,结果可能是0~10

如果n mod 11的值是8、9、10那么1次查找之后就可以判定表中不存在这个值,

如果n mod 11 = 0,那么还需要偏移,一共9次查找才能判定表中没有这个值,

如果n mod 11 = 1,那么需要8次查找才能判定表中没有这个值,

如果n mod 11 = 2,那么需要7次查找才能判定表中没有这个值,……

如果n mod 11 = 7,那么需要2次查找才能判定表中没有这个值。所以不成功的平均查找长度就是上述查找次数取均值

7、

① 索引仅满足“=”、“IN”和“<=>”查询,不能使用范围查询因为hash索引比较的是经常hash运算之后的hash值,因此只能进行等值的过滤,不能基于范围的查找,因为经过hash算法处理后的hash值的大小关系,并不能保证与处理前的hash大小关系对应。

② hash索引无法被用来进行数据的排序操作。由于hash索引中存放的都是经过hash计算之后的值,而hash值的大小关系不一定与hash计算之前的值一样,所以数据库无法利用hash索引中的值进行排序操作。

③ 对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。

④ Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。

8、哈希表(Hash Table)是一种根据关键字直接访问内存存储位置的数据结构。通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种对应关系。

A,hash函数可以把字符串等任意长度的输入映射成固定长度的整数,也就是哈希值。

C,哈希表建立了哈希值与原值信息存储之间的联系,可以通过哈希值查找到原值信息。

D,不同的信息产生相同的哈希值叫哈希冲突。设计哈希函数应尽量避免哈希冲突。因此一般很难冲突。

9、散列的基本思想是以结点的关键码作为自变量,通过散列函数将其映射到记录的存储地址。有时不同的关键码值经过同一散列函数计算后形成相同的存储地址,产生碰撞现象。由于处理碰撞的代价较大,应尽量避免。这就要求散列函数在作用于各记录关键码后的取值能同等均匀在存储空间上。

10、散列表的查找效率取决于:散列函数、处理冲突的方法和装填因子。

11、开哈希表-------链式地址法,闭哈希表-------开放地址法

开哈希只会和相同值发生冲突,而闭哈希除了与相同值发生冲突,还会与不同值发生冲突。所以,开哈希不受密度影响,而闭哈希受密度影响

12、现有一完全的P2P共享协议,每次两个节点通讯后都能获取对方已经获取的全部信息,现在使得系统中每个节点都知道所有节点的文件信息,共17个节点,假设只能通过多次两个对等节点之间通讯的方式,则最少需要(30)次通讯。【记住】2n - 4次。

时间: 2024-11-05 06:10:26

随笔64 hash表的相关文章

hdu 5183 hash表

BC # 32 1002 题意:给出一个数组 a 和一个数 K ,问是否存在数对( i , j ),使 a i   - a i + 1 +……+ (-1)j - i  a j : 对于这道题,一开始就想到了是前缀和,但是如果只是记录下前缀和数组,那么查找就会成为一个大问题.补题的时候一开始考虑用 hash 数组或者是 set 存,但是很明显 TLE 了,在翔神的推荐下,我研究了一下 hash表的创建过程,惊奇地发现,其实就是建了一个 HashMap 结构体,而里面放了这个表所用的数组以及相应操作

hash表的建立和查找

(1)冲突处理方法为:顺次循环后移到下一个位置,寻找空位插入.(2)BKDE 字符串哈希unsigned int hash_BKDE(char *str){/* 初始种子seed 可取31 131 1313 13131 131313 etc.. */unsigned int seed = 131;unsigned int hash = 0;while (*str){hash = hash * seed + (*str++);}return (hash & 0x7FFFFFFF);} 选做内容每一

HDU 5183 Negative and Positive (NP) ——(后缀和+手写hash表)

根据奇偶开两个hash表来记录后缀和.注意set会被卡,要手写hash表. 具体见代码: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 using namespace std; 5 const int N = 1000000 + 10; 6 const int HASH = 1000000 + 7; 7 typedef long long ll; 8 struct hashmap

深入了解STL中set与hash_set,hash表基础

一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(logN)的情况下插入,删除和查找数据.hash_set操作的时间度则比较复杂,取决于哈希函数和哈希表的负载情况. 二,SET使用范例(hash_set类似) 1 #include <set> 2 #include <ctime> 3 #include <cstdio> 4

十一、从头到尾彻底解析Hash 表算法

在研究MonetDB时深入的学习了hash算法,看了作者的文章很有感触,所以转发,希望能够使更多人受益! 十一.从头到尾彻底解析Hash 表算法 作者:July.wuliming.pkuoliver  出处:http://blog.csdn.net/v_JULY_v.  说明:本文分为三部分内容,    第一部分为一道百度面试题Top K算法的详解:第二部分为关于Hash表算法的详细阐述:第三部分为打造一个最快的Hash表算法.----------------------------------

Hash表算法

出处:http://blog.csdn.net/v_JULY_v 第一部分:Top K 算法详解问题描述百度面试题:    搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.    假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个.一个查询串的重复度越高,说明查询它的用户越多,也就是越热门.),请你统计最热门的10个查询串,要求使用的内存不能超过1G. 必备知识:    什么是哈希表?    哈希

从头到尾彻底解析Hash 表算法

在研究MonetDB时深入的学习了hash算法,看了作者的文章很有感触,所以转发,希望能够使更多人受益! 十一.从头到尾彻底解析Hash 表算法 作者:July.wuliming.pkuoliver  出处:http://blog.csdn.net/v_JULY_v.  说明:本文分为三部分内容,    第一部分为一道百度面试题Top K算法的详解:第二部分为关于Hash表算法的详细阐述:第三部分为打造一个最快的Hash表算法.----------------------------------

从头到尾彻底解析Hash表算法

作者:July.wuliming.pkuoliver 说明:本文分为三部分内容, 第一部分为一道百度面试题Top K算法的详解:第二部分为关于Hash表算法的详细阐述:第三部分为打造一个最快的Hash表算法. 第一部分:Top K 算法详解 问题描述(百度面试题): 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节.假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个.一个查询串的重复度越高,说明查询

Hash表 算法的详细解析

http://xingyunbaijunwei.blog.163.com/blog/static/76538067201111494524190/ 什么是HashHash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值.简单的说就是一种将任意长度的消息