【Algorithms 4】算法(第4版)学习笔记 14 - 3.4 散列表(Hash Tables)

前言

说起来挺丢脸的哈哈哈,在打开这一章之前,或者说是打开这一章节视频(官网)之前,我不知道 散列表 居然就是 Hash Tables,也就是每一个会敲代码的人应该都用过的哈希表(属实是汗流浃背了朋友们)。所以我特意在本篇的标题后面打了个括号:(Hash Tables)

继续批评一下自己,说明基础太薄弱了,还得继续学习。不过说实话散列表说起来确实是不太习惯,所以 在本篇中还是尽量使用哈希来代替中文翻译的散列

Ok,回到正题,本篇的主要内容包括:哈希函数分离链接Separate Chaining,这个书里面中文翻译成 拉链法)、线性探测 以及一点点关于哈希的 背景context) 介绍。

参考目录

  • B站 普林斯顿大学《Algorithms》视频课
    (请自行搜索。主要以该视频课顺序来进行笔记整理,课程讲述的教授本人是该书原版作者之一 Robert Sedgewick。)
  • 微信读书《算法(第4版)》
    (本文主要内容来自《3.4 散列表》)
  • 官方网站
    (有书本配套的内容以及代码)

学习笔记

注1:下面引用内容如无注明出处,均是书中摘录。
注2:所有 demo 演示均为视频 PPT demo 截图。
注3:如果 PPT 截图中没有翻译,基本会在下面进行汉化翻译(除非很简单一眼懂就不翻译了),因为内容比较多,本文不再一一说明。

开篇的时候,Prof. Sedgewick 是这样介绍哈希表的:

Which is another approach to implementing symbol tables that can also be very effective in a practical applications.
这是实现符号表的另一种方法,在实际应用中也非常有效。

0:符号表(ST)实现小结

在这里插入图片描述

哈希表的简单引出:

在这里插入图片描述

将项目存储在 键索引表 中(索引是基于键的一个函数)。
哈希函数。用于从键计算数组索引的方法。

涉及的问题

  • 计算哈希函数(设计并实现一个有效的哈希函数以将键转化为数组索引。)
  • 等价性测试:一种方法用于检查两个键是否相等。
  • 冲突解决:当两个键通过哈希函数映射到同一个数组索引时,所采用的算法和数据结构来处理这种冲突。

经典的空间-时间权衡

  • 无空间限制情况:可以使用简单的哈希函数,直接将键作为数组索引。
  • 无时间限制情况:可以采用顺序搜索进行最直观的冲突解决,无需特别的数据结构优化。
  • 空间和时间受限情况:在实际应用中,需要兼顾时间和空间效率,这时就需要运用到真正的哈希技术。

1:哈希函数

1.1:计算哈希函数

在这里插入图片描述

理想目标:对键进行均匀随机打乱以生成表索引。

  • 计算效率高。
  • 对于每个键,每个表索引具有同等的概率被生成。(这是一个经过深入研究但仍存在实际应用问题的难题)

示例 1:电话号码。

  • 不好:前三位。
  • 更好:最后三位数字。

美国的电话前三位是区号,可以考虑日常生活中的电话号码,前三位一般是所属运营商,通常情况下会使用后四位数字进行简单区分(例如取快递报手机号后四位)。

示例 2:社会保险号。

  • 不好:前三位。(573 = 加利福尼亚州,574 = 阿拉斯加(按地理区域内的时间顺序分配)
  • 更好:最后三位数字。

书里面的相关描述:

在这里插入图片描述

实际挑战:每种密钥类型需要不同的方法。

1.2:Java中的哈希码规范

在这里插入图片描述

所有 Java 类都继承了一个方法 hashCode(),该方法返回一个 32 位整数。

要求:如果 x.equals(y),则 (x.hashCode() == y.hashCode())
高度期望:如果 !x.equals(y),则 (x.hashCode() != y.hashCode())

默认实现:返回对象x的内存地址。
合法(但较差)的实现:始终返回 17。
定制化实现示例:Integer、Double、String、File、URL、Date 等。
用户自定义类型:对于用户自定义的类型(需要自行设计和实现)。

1.2.1:哈希码实现:integers、booleans、doubles

在这里插入图片描述

找了一下 jdk 包的源码:
Oracle OpenJDK version 11.0.6

java.lang.Integer#hashCode

在这里插入图片描述

java.lang.Boolean#hashCode

在这里插入图片描述

java.lang.Double#hashCode

在这里插入图片描述

1.2.2:哈希码实现:strings

在这里插入图片描述

霍纳法则(Horner’s method)用于计算长度为L的字符串哈希值:需要进行L次乘法和加法操作。

在这里插入图片描述

同样地,找了一下 jdk 包的源码(不过版本差异因此实现有出入,这里看一下 jdk 11 以及 jdk 8 的实现):
Oracle OpenJDK version 11.0.6

java.lang.String#hashCode
在这里插入图片描述

jdk 11 区分了不同的字符集 StringUTF16 以及 StringLatin1

java.lang.StringUTF16#hashCode

在这里插入图片描述

java.lang.StringLatin1#hashCode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MichelleChung

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值