0
点赞
收藏
分享

微信扫一扫

数据结构之散列表与哈希函数初识

一:概述

一:为什么需要散列表

* 在我们的程序世界里,往往也需要在内存中存放这样一个“词典”,方便我们进行高效的查询和统计。

* 例如开发一个学生管理系统,需要有

* 通过输入学号快速查找对应学生的姓名的功能。

* 这里不必要每次都去查询数据库,而可以在内存中建立一个缓存表,这样做可以提高

* 查询效率。
*           学号          姓名
*           001121        张三
*           002123        李四
*           002931        王五
*           003278        赵六
*
* 再如我们需要统计一本英文书里面单词出现的频率,就需要遍历整本书的内容
* 把这些单词出现的次数记录在内存中。
*          单词             出现次数
*          this               108
*          and                56
*          are                79
*          by                 46
* 因为这个需求,一个重要的数据结构诞生了,这个数据结构叫作散列表。
*
* 散列表i也叫作哈希表(hash table),这种数据结构提供了键(key)和值(value)的映射关系
* 只要给出一个key,就可以高效的查找它所匹配的Value,时间复杂度接近于O(1)。
*

二:哈希函数

* 在数组、链表、栈、队列中,数组的访问效率最高,对元素进行随机的访问

* 散列表在在本质上也是一个数组。

*

* 数组只能根据下标,像a[1]、a[2]、a[3]、a[4]、a[5]这样来访问,而散列表的Key则是以字符串

* 类型为主的。

* 例如以学生的学号作为Key,输入002123,查询到李四;或者以单词为Key,输入by,查询到数字

* 46.....

* 需要一个“中转站”,通过某种方式,把Key和数组下标进行转换。这个中转站就叫做哈希函数。

* 哈希函数的实现:
* 在不同的语言中,哈希函数的实现方式是不一样的。这里以Java常用集合HashMap为例。
* 来看一看哈希函数在Java中的实现。
*
* 在Java及大多数面向对象的语言中,每一个对象都有属于自己的hashcode,这个hashcode
* 是区分不同对象的重要标识。无论对象自身的类型是什么,它们的hashcode都是一个整型变量。
*
* 既然是一个整型变量,想要转换成数组的下标也就不难实现了。
* 最简单的实现方式就是按照数组的长度取模运算。
*   即:index = HashCode(Key) % Array.length
* 实际上,JDK(Java Development Kit,Java语言的软件开发工具包)中的哈希函数
* 并没有直接采取取模运算,而是利用了位运算的方式来优化性能。不过在这里姑且简单理解成
* 取模操作
*
* 通过哈希函数,我们可以把字符串或其他类型的Key,转换成数组的下标index。
* 如给出一个长度为8的数组,则当
* key = 001121时,
*     index = HashCode("001121") % Array.length = 1420036703  %8 = 7
*而当key = this时,
*     index = HashCode("this") % Array.length = 3559070 % 8 = 6 ;
*

举报

相关推荐

0 条评论