您的位置:首页 > 理论基础 > 数据结构算法

“学习笔记”之《算法导论》----第三部分----数据结构----第十一章----散列表

2019-01-26 09:57 78 查看
版权声明:未经博主允许,勿转载 https://blog.csdn.net/qq_34754836/article/details/86654028

本人大四即将结束,于2018年12月18日购《算法导论》这本书,慢慢看,第一阶段先主要理解各个章节说的算法都是什么意思,书上的课后习题先不做,用得上什么算法我再详细学习。这是官方课后答案的链接

放在开头:没有好的算法,坏的算法之说,重点是针对不同的情况,针对不同的数据,针对不同的需求,去选择算法,改良算法。我的数学功底不强,太难的公式我看不懂,太高深的思想我理解不了,我主要以应用为主,不以解释数学公式为主。

散列表是数组和链表的结合体。继承了数组寻找数据快的优点,继承了链表插入或删除数据块的优点。

直接寻址表

这个东西其实就是数组啊。通过下标寻找元素。

散列表

直接寻址的缺点很明显,就是当这个“数组”很大的时候,很多资源就会造成浪费。比如,你这个数组第一个元素是array[0],第89个元素是array[88],中间80多个空位置没用,就会造成资源的浪费。这个情况我总结一下就是:下标太多了,数据不多。资源浪费,不好。

下面正式引出散列表。

现提出这样一个想法,我们如果能通过一个映射,将众多的数组下标,转换到少数的数据上。比如,我们数组大小是100个元素,我们要映射到几十个数据上,就像array[0]和array[3]这两个指向的同一个数据(专业点叫),这个数据不是简单的数,数据(槽)的里面就是链表(双向链表)。

当两个或者多个关键字映射到同一个槽上,那么我们就把多个数据转化成链表的形式,储存在同一个槽中。

像下面这个图一样,我们的下标(专业点叫关键字)很多,但是槽就十几个,而且有的槽还用不上,有几个槽用上了,里面的数据是一串链表。好比什么呢?就是手机通讯录,姓名排序,A字母有姓安的,W字母有姓王的,等等。

                                                

那么怎么映射呢?这个涉及到散列函数,h(x),x输入就是我们的众多的下标(关键字),输出出来的就是槽的位置。

我们上面这个图我百度找的,有些小瑕疵。就是我们的链表最好是双向的,这样便于我们的删除和插入操作。

散列函数 

如果我们的所有元素都跑到了一个槽中,那么我们这个散列表就白做了,就是个链表了。

所以我们要求散列函数得好。好的散列函数应该能将这些相近符号散列到相同槽中的可能性最小化

三种设计散列函数的方法。

除法散列法:h(k)=k mod m。k是关键字,m是我们要选的。m的选择方法是,一个不太接近2的整数幂的素数。

乘法散列法:h(k)=向下取整m(kA mod 1)。k是关键字,先是k*A(0<A<1),然后取它的小数部分,然后再乘以m,然后向下取整数。A 推荐选择 0.618。

全域散列法:多选几个散列函数,然后用的时候随机选。设计这几个散列函数,需要用到数论的知识,回头我补充。

总之呢,散列函数的目的,就是使这几个槽都有东西,越平均越好。

开放寻址法

这个。。。我怎么看怎么像是一个普通的数组储存方法。难不成是我理解有误???

所有的数据都在槽里面的第一个元素。没有链表。

本节介绍了三种找数据的方式:线性探查,二次探查,双重散列。他们都是通过散列函数的方式来寻找数据的,前两种方式我不详细说了,因为它没有第三种好。

双重散列:h(k,i) = (h1(k)+i*h2(k)) mod m。它的优点在于,变量有很多,h1(k),h2(k),都可以变化,而且初始的探查位置也可以变化。这样,我们寻找元素的平均速度更快,不像我们从头开始一个一个找,这个方法像是一跳一跳的,而且没个槽都能跳到,关于这两个函数的选择方法我也先不写了,以后用到了再看。

完全散列

简单说就是多级散列。比如我们有一个散列表,某一个槽上有多个数据,需要用链表储存,然后链表的尾部又有一个散列表,又有了一堆槽供我们使用。

重点就是散列函数以及二级散列表的大小的选择。

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