跳转至

第 14 章 数据结构总结

原作:Josh Hug,UC Berkeley CS61B Spring 2021 配套读本。
中文翻译版,仅供非商业学习;采用 CC BY-NC-SA 4.0 许可。
原始网站:https://joshhug.gitbooks.io/hug61b/content/



14.1 数据结构总结

搜索问题

我们面对的基本问题是:给定持续到来的数据流,如何取回自己关心的信息?

例如:

  • 用户在个人主页发布内容,但只向好友展示。
  • 根据成千上万个气象站的日志,显示某个日期和时刻的天气地图。
  • 宠物主人寻找“最好”的宠物店,而“最好”可能按价格、质量或氛围定义。

目前学习的各种数据结构,本质上都在解决搜索问题。它们采用不同的组织方式,让特定场景下的检索更高效。

常见搜索 ADT

名称 存储操作 主要取回操作 取回依据
List add(key)insert(key, index) get(index) 索引
Map put(key, value) get(key) 键的身份
Set add(key) contains(key) 键的身份
Priority Queue add(key) getSmallest() 键的顺序或优先级
Disjoint Sets connect(a, b) isConnected(a, b) 两个元素的连通性

这些都是抽象数据类型:它们定义行为,而不是实现。前面各章已经讨论了许多可能的底层结构。

同一种实现可以服务多个 ADT,但并不是每种组合都高效。图中性能较差的实现提醒我们:能实现某种行为,不代表它就是合适的选择。

练习 14.1.1:思考如何修改每种实现以适配目标 ADT。例如,哈希表怎样勉强实现优先队列?为什么性能不理想?

抽象的层次

抽象经常分层出现。一个 ADT 的实现本身,也可能依赖另一个 ADT。

  • 优先队列可以用堆序树实现;而堆序树又可以用直接结点指针、父结点数组或层序数组等多种方式表示。
  • 拉链哈希表由“桶数组”组成;每个桶又可以使用 ArrayList、动态数组、链表或 BST。

因此,我们常常用一个 ADT 来构建另一个 ADT。每一层抽象只规定自己关心的行为,并把更底层的实现细节隐藏起来。这种分层让程序更容易替换实现、比较权衡和控制复杂度。