寒假复习感想——数据结构篇其二__hash

Hash

哈希表(hash table)的思路是根据关键码值直接访问。

 

哈希表的思路很简单——根据关键码值直接计算出信息的存储地址。

通常会为hash table 分配一个一维数组的存储空间,二维数组或多维数组用得比较少

但是多维数组应用到hash table上面有一些好处:

在多关键字的情况下 hash函数的设计 显得自然

 

设hash 函数是  h(K)

Hash表一般支持以下几个操作。

1.  插入:计算h(K)并插入

2.  查找:计算h(K)并访问

3.  删除:增加一些删除标记,以后统一删除(较少使用)

 

Hash的使用有两个比较需要注意的地方:

1.  Hash函数的设计

2.  冲突的解决方法

 

常用的hash函数:直接取余法,平方取中法,折叠法,ELFhash函数(字符串)

在hash函数方面前人做过很多研究,想要在这方面做突破需要对其有很深刻的理解和很细致入微的研究,所以我们现在只需要直接拿来用就好了^^.

 

冲突解决方法,一般是开散列法,不赘述。

 

到目前为止,实现hash表所需要知道的最基本的东西已经差不多了,但是还有一个很关键的问题没有解决——hash是用来干嘛的?(虽然笼统一点可以说  hash是用来解决查询次数多且数据分布相对随机的应用的,但是太过抽象,不够具体)

 

有一道例题:

例一:促销

      促销活动遵循以下原则:“参与本活动的顾客,应将自己的个人信息写在所付账单背面,并将账单投入指定的箱子。在每天的销售结束后,箱子中消费金额最大和最小的两个顾客奖杯选出。消费最多的顾客将得到一笔奖金,奖金的数目等于两张账单金额之差。为了避免因为一次消费而得到多笔奖金,依照以上原则选出的两张账单将不被放回到箱子中,但箱子里剩下的账单可以继续参加第二天的活动。”

       你的任务是根据每天投入箱子的所有账单,计算出整个促销活动中超市要付出的奖金总额。本题中约定:

1.  整个促销活动持续了n天,n<=5000

2.  第i天放入的钞票有a[i]张,a[i]<=100000,且s=∑a[i]<=1000000

3.  第i天放入的钞票面值分别是bi[1],bi[2],。。。bi[a[i]],bi[j]<=1000000

分析:这个应用下的数据规模是很大的,采用普通的线性表的话,复杂度差不多是O(ns),也就是 差不多要计算     5000X1000000次!!!!,这么做的话是会慢到爆的。。。

      但是用分段hash表的话,可以把复杂度降到O(s+(nm)^0.5)(其中m是总长度,在分段hash表中,每一段的长度是  (m)^1/2),也就是差不多计算 1000000+100000次,比第一种方法快了将近5000倍。。。。。。

上面一道例子反应了hash表的一类应用(我不太会描述)。~~

 

hash有一种应用是判重,我们知道解决字符串匹配有一些高效算法,例如基于自动机的kmp算法,除了kmp算法之外,还有一个平均性能不错的算法:rabin-karp 算法,某种意义上其实可以把它算作是hash表的应用。(rabin-karp友情链接:http://www.cnblogs.com/feature/articles/1813967.html

 

如果熟悉了rabin-karp,那么有一个二维匹配的应用可以用近乎一样的思想解决:

例2:equal squares

在一个N*M的字符矩阵中找到两个相同的子正方形矩阵(可以相交),并使找到的两个子正方形的矩阵边长尽量大。

分析:比较快的解法有两个:二维的KMP和hash表。。。。而且由于这是找子矩阵,所以二维KMP的效果还不如hash好,hash解法的复杂度是  O(mnlog(mn))

 

Hash判重还有一些其他的应用方式,例如判循环等等,判有根树的同构,判定无根树的同构,判定有向图的同构(这些都能通过hash得到很好的解决,这三个判定图的同构问题的解法复杂度都是O(NlogN))等等。。不一一列举了

 

写到这里,越发觉得hash的神奇了,因为我很难像并查集那样概括出它的用途,它似乎并没有太明显的针对性,这就表示,它的应用可能会很巧妙(比如和编码联系在一起的时候的hash函数 的设计,而编码本身就是一个很奇妙的东西。。。)。。。

好吧,才太疏学太浅了。。。。。。希望能在在以后的学习中对hash有更深入的理解。

转载于:https://www.cnblogs.com/njuzyc/archive/2012/01/23/2328976.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值