5.1 散列
定义
理想的散列表是一个包含有关键字的具有固定大小的数组。关键字就是带有相关值的字符串。表的大小记作Table-Size,关键字被映射到从0到TableSize - 1这个范围中的某个数。
散列函数
映射
关键字被映射到0到TableSize - 1这个范围中的某个数,并且被放到适当单元中。这个映射就叫做散列函数。
理想散列函数
理想情况下它应该运算简单并且应该保证任何两个不同的关键字映射到不同的单元。
冲突
当两个关键字映射到同一个值的时候,称为冲突,需要选择函数来解决冲突。
5.2 散列函数
key mod size
使用
关键字为整数,一般合理方法就是直接返回“key mod size”。
缺点
关键字一般都为字符串
字符ASCII码的和 mod size
使用
将关键字字符串中字符的ASCII码值加起来。
缺点
char的值最多为127,如果8个字符长,关键字ASCII和在0到1016之间,如果size过大,就不能映射到后面。
关键字至少三个字符时
使用
缺点
英文不是随机的,三个字母的不同组合中的28%才能被真正用到。
一个好的散列函数
使用
用32代替27,因为32作乘法是移动五位二进制
缺点
如果关键字特别长,该散列函数计算起来将会花费过多的时间。
5.3 分离链接法
思想
将散列到同一个值的所有元素保留到一个表中。
缺点
需要指针,给新单元分配地址需要时间。
5.4 开放定址法
线性探测法
思想
F(i) = i
缺点
占据的单元容易形成区块,称为聚集。当表有多于一半被填满的话,线性探测法的效率就会很低。
平方探测法
思想
F(i) = i^2,当冲突时,其下一个位置为1、4、9。。。
规律
如果表有一半是空的,并且表的大小是素数,那么保证总能插入一个新元素。
缺点
会造成二次聚集,虽然排除了一次聚集,但是散列到同一位置上的那些元素将探测相同的备选单元。
双散列、再散列、可扩散列
思想
将第二个散列函数
散列的应用
符号表
编译器跟踪源代码中声明的变量
图论
节点的名字映射到数字,方便查找
二叉搜索树和散列
如map和unordered_map,前者红黑树实现,后者散列表实现,前者可以排序,后者操作更快
相同点
可以实现Insert和Find
不同点
二叉搜索树更方便排序,如找出最小元素等。
二叉搜索树的插入和查找操作为O(logN),而散列为O(1)