目录
一. 认识哈希表
哈希表是一种非常重要的数据结构,几乎所有的编程语言都有直接或者间接的应用这种数据结构。
哈希表通常是基于数组进行实现的, 但是相对于数组,,它有很多的优势:它可以提供非常快速的插入-删除-查找操作。无论多少数据, 插入和删除值需要接近常量的时间:即O(1)的时间级。
哈希表的速度比树还要快,基本可以瞬间查找到想要的元素。哈希表相对于树来说编码要容易很多。
哈希表的结构就是数组,但是它神奇的地方在于对下标值的一种变换,这种变换我们可以称之为哈希函数,通过哈希函数可以获取到HashCode。
哈希表相对于数组的一些不足:哈希表中的数据是没有顺序的,所以不能以一种固定的方式(比如从小到大)来遍历其中的元素。
通常情况下,哈希表中的key是不允许重复的,不能放置相同的key,用于保存不同的元素。
案例:1000个学生信息需要使用某种数据结构来保存,采用什么数据结构?
方法一:数组
一种方案是按照顺序将所有的学生依次存入一个长度为1000的数组中。每个学生的信息都保存在数组的某个位置上。但是要查看某个具体学生的信息时不太好找。数组最大的优势是什么可以通过下标值去获取信息。所以为了可以通过数组快速定位到某个学生,最好给学生信息中添加一个学生编号,而编号对应的就是学生的下标值。当查找某个学生的信息时, 通过学生编号可以快速定位到学生的信息位置。
方法二: 链表
链表对应插入和删除数据有一定的优势。但是对于获取学生的信息,每次都必须从头遍历到尾。
方案三: 有没有一种方案, 可以将学生姓名和数组的下标值对应呢?
让学生的姓名作为下标值,来获取这个学生对应的信息。但是学生的姓名(字符串)不可以作为下标值。所以需要一种方案将字符串转成下标值。
-
但是, 怎样才能将一个转成数组的下标值呢?
单词转下标值,其实就是字母转数字,可以使用编码系统:- 比如ASCII编码:a是97,b是98,依次类推122代表z
- 也可以设计一个自己的编码系统,比如a是1,b是2,c是3,依次类推,z是26。可以加上空格用0代替,就是27个字符(不考虑大写问题)
- 计算机中有很多的编码方案就是用数字代替单词的字符。
- 方案一:幂的连乘
平时使用的大于10的数字,可以用一种幂的连乘来表示它的唯一性:比如: 7654 = 7*10³+6*10²+5*10+4。就算能创建这么大的数组,事实上有很多是无效的单词。创建这么大的数组是没有意义的。这样得到的数字几乎可以保证它的唯一性,不会和别的单词重复。
另外,单词也可以使用这种方案来表示: 比如cats = 3*27³+1*27²+20*27+17= 60337
- 方案二:数字相加
把单词每个字符的编码求和。例如单词cats转成数字:3+1+20+19=43,那么43就作为cats单词的下标存在数组中。这种方案的问题是很多单词最终的下标可能都是43。然而数组中一个下标值位置只能存储一个数据,如果存入后来的数据,必然会造成数据的覆盖。一个下标存储这么多单词显然是不合理的。
第一种方案产生的数组下标太多,第二种又太少。