`

(好!)哈希表算法通俗理解和实现

 
阅读更多

顺序查表法

假设现在有1000个人的档案资料需要存放进档案柜子里。要求是能够快速查询到某人档案是否已经存档,如果已经存档则能快速调出档案。如果是你,你会怎么做?最普通的做法就是把每个人的档案依次放到柜子里,然后柜子外面贴上人名,需要查询某个人的档案的时候就根据这个人的姓名来确定是否已经存档。但是1000个人最坏的情况下我们查找一个人的姓名就要对比1000次!并且人越多,最大查询的次数也就越多,专业的说这种方法的时间复杂的就是O(n),意思就是人数增加n倍,那么查询的最大次数也就会增加n倍!这种方法,人数少的时候还好,人数越多查询起来就越费劲!那么有什么更好的解决方法吗?答案就是散列表算法,即哈希表算法。

哈希表算法

假设每个人的姓名笔划数都是不重复的,那么我们通过一个函数把要存档的人姓名笔划数转换到1000以内,然后把这个人的资料就放在转换后的数字指定的柜子里,这个函数就叫做哈希函数,按照这种方式存放的这1000个柜子就叫哈系表(散列表),人名笔画数就是哈系表的元素,转换后的数就是人名笔划数的哈希值(也就是柜子的序号)。当要查询某个人是否已经存档的时候,我们就通过哈希函数把他的姓名笔划数转化成哈希值,如果哈希值在1000以内,那么恭喜你这个人已经存档,可以到哈希值指定的柜子里去调出他的档案,否则这个人就是黑户,没有存档!这就是哈希表算法了,是不是很方便,只要通过一次计算得出哈希值就可以查询到结果了,专业的说法就是这种算法的时间复杂是O(1),即无论有多少人存档,都可以通过一次计算得出查询结果!

当然上面的只是很理想的情况,人名的笔划数是不可能不重复的,转换而来的哈希值也不会是唯一的。那么怎么办呢?如果两个人算出的哈希值是一样的,难道把他们都放到一个柜子里面?如果1000个人得出的哈希值都是一样的呢?下面有几种方法可以解决这种冲突。 

 

开放地址法

这种方法的做法是,如果计算得出的哈希值对应的柜子里面已经放了别人的档案,那么对不起,你得再次通过哈希算法把这个哈希值再次变换,直到找到一个空的柜子为止!查询的时候也一样,首先到第一次计算得出的哈希值对应的柜子里面看看是不是你要找的档案,如果不是继续把这个哈希值通过哈希函数变换,直到找到你要的档案,如果找了几次都没找到而且哈希值对应的柜子里面是空的,那么对不起,查无此人!

拉链法(链地址法)

这种方法的做法是,如果计算得出的哈希值对应的柜子里面已经放了别人的档案,那也不管了,懒得再找其他柜子了,就跟他的档案放在一起!当然是按顺序来存放。这样下次来找的时候一个哈希值对应的柜子里面可能有很多人的档案,最差的情况可能1000个人的档案都在一个柜子里面!那么时间复杂度又是O(n)了,跟普通的做法也没啥区别了。在算法实现的时候,每个数组元素存放的不是内容而是链表头,如果哈希值唯一,那么链表大小为1,否则链表大小为重复的哈希值个数。

公共溢出区

这种方法跟拉链法也差不多,如果计算得出的哈希值对应的柜子里面已经放了别人的档案,那么就把这个人放到另外一个档案室里面哈希值对应的柜子里面,这样哈希值是一样的,但是档案室不同了。查找的时候根据得到哈希值去不同档案室分别查找,直到找到档案或者没有找到档案为止。这样其他的那些档案室就叫做公共溢出区。

 

通过上面的描述可以看出,所谓的哈希表算法复杂度也不一定就是理想的O(1),但即便如此,还是比普通的顺序查表法速度快多了,因为不可能所有的哈希值都是一样的,如果那样的话,只能说明你的哈希函数不够优秀,你要做的就是换一个哈希函数!一个好的哈希函数应该尽可能让要保存的内容平均的分布在哈希表上。常用的哈希函数有:直接定址法、求余法、数字分析法、平方取中法、折叠法、随机数法等。下面是最常用的求余法。

求余法哈希函数

这种方法就是用人名笔画数除以一个常数,最后的余数就是哈希值。这就是最简单也是最常用的哈希函数。当然这个常数的取法也是就讲究的,一句话,最好是一个跟2或者10的乘幂差值比较大的素数!这种方法的缺陷就是比较耗时,因为除法取余在CPU执行的时候比其他算数运算用的时钟周期更长!

 

 

REFS:    http://blog.csdn.net/u013752202/article/details/51104156

分享到:
评论

相关推荐

    通俗易懂的算法设计课件

    链表、栈、队列、树、哈希表等数据结构的特性和操作,为实现各种算法提供了基础。理解这些数据结构及其操作,能帮助我们更好地设计和选择合适的算法。 课件中的实例和练习是巩固理论知识的好方法。通过解决实际问题...

    算法练习,常见算法,面试常用

    此外,数据结构如堆、哈希表、红黑树等的理解和使用也是面试的重点。 对于Go语言,其特有的channel和goroutine使得在实现并发算法时更加方便,如Fibonacci序列的并发计算就是典型的例子。理解并掌握这些算法和数据...

    算法设计和分析,王晓东

    在《算法设计和分析》中,王晓东教授可能涵盖了一些经典算法,如排序算法(快速排序、归并排序、堆排序等)、查找算法(二分查找、哈希表查找等)和图算法(Dijkstra最短路径算法、Floyd-Warshall全网最短路径算法、...

    算法艺术入门 pdf 【高清】

    3. **排序与搜索**:排序算法(如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序)和搜索算法(如线性搜索、二分搜索、哈希搜索)是算法的基石。书中会详尽解析这些算法的工作原理,并通过实例展示其...

    小甲鱼数据结构与算法课件+源码.zip_-baijiahao_expresschs_once4l3_小甲鱼 ppt_小甲鱼数据结

    常见的数据结构包括数组、链表、栈、队列、哈希表、树(二叉树、平衡树如AVL和红黑树)、图等。这些数据结构各有特点,适用于不同的场景,理解它们的特性和操作方法是编程能力提升的关键。 例如,数组是最基础的...

    算法(第四版)

    2. **数据结构**:数据结构是算法的载体,包括数组、链表、栈、队列、哈希表、树(二叉树、平衡树如AVL和红黑树)和图等。书中通过实例详细讲解了各种数据结构的特性、操作和应用场景,使读者能熟练运用这些数据结构...

    程序员实用算法

    例如,在软件开发中,我们常常需要优化数据结构来提升性能,如使用哈希表进行快速查找,或者使用堆实现优先队列。同时,理解和运用贪心算法、回溯算法和分支限界法,可以帮助解决许多组合优化问题。 学习算法不仅仅...

    常用算法程序集(C语言描述)(第三版)+源代码修改.rar

    - 搜索算法:如线性搜索、二分查找、哈希表查找等,用于在数据结构中寻找特定元素。 - 图论算法:例如最短路径算法(Dijkstra算法、Floyd-Warshall算法)、拓扑排序等,广泛应用于网络优化和路线规划问题。 - ...

    算法演示-严蔚敏版数据结构

    这份压缩包文件包含了书中算法的演示,帮助读者更好地理解和应用这些概念。 数据结构是计算机科学的基础,它研究如何在计算机中组织和存储数据,以便于高效地访问和操作。了解和掌握数据结构能提升程序的性能和可...

    java数据结构和算法

    这本书以其通俗易懂的语言和生动的Applet演示程序,为读者提供了直观的学习体验,使得抽象的算法概念得以具象化,便于理解和掌握。 1. **数据结构基础** - **数组**:作为最基础的数据结构,数组是存储和访问固定...

    《图解数据结构与算法》正文试读页

    最后介绍了一些高级的数据结构和算法,如哈希表、Bloom Filter和图论等。 这本书采用“少字多图”的方式,略过复杂的数学公式,用通俗易懂的方式针对编程初学者介绍数据结构与算法的基本概念,培养读者编程逻辑。...

    刘汝佳黑白书合集,算法竞赛ACM经典

    2. **数据结构**:包括链表、栈、队列、树(如二叉树、平衡树AVL、红黑树等)、图、哈希表等。数据结构的选择直接影响到算法的效率,理解它们的特性和适用场景是学习算法的关键。 3. **ACM竞赛策略**:书中可能包含...

    程序员实用算法5,Andrew Binstock John Rex

    - **哈希表**:通过哈希函数实现快速查找,适用于多种应用场景。 ##### 3. 实战案例 - **动态规划**:解决诸如背包问题、最长公共子序列等优化问题的有效手段。 - **贪心算法**:在特定条件下寻找最优解的快速方法...

    经典教材-算法导论-英语版

    它不仅介绍了大量的算法,而且还深入探讨了这些算法的设计与分析方法,使得不同水平的读者都能够理解和掌握。作者们努力保持讲解的通俗易懂,同时又不牺牲深度和数学严谨性。 每一章都围绕一个算法、一种设计技术、...

    南大C语言数据结构--通俗易懂版

    第八章查找,讲解不同的查找算法,如顺序查找、二分查找以及哈希表查找。高效查找对于提高程序运行效率至关重要。 最后,第九章排序,涵盖了各种排序算法,如冒泡排序、插入排序、选择排序、快速排序、归并排序等。...

Global site tag (gtag.js) - Google Analytics