数据结构:练习题及解析

免费的数据结构选择练习题,附提示和解析,分三个难度:关键术语与事实, 概念应用, 案例与分析。

免费练习题简单

最大堆性质是什么?

下一题 →
免费练习数据结构立即练习数据结构每天 5 道免费题目,无需绑定银行卡。

练习内容

  1. 简单关键术语与事实
  2. 中等概念应用
  3. 困难案例与分析

从零开始学习数据结构

学习本课之前: 算法与复杂度

1什么是数据结构

数据结构是在内存中组织数据的一种方式,使某些操作很快:查找一个项目、添加一个、删除一个。

没有哪种结构在所有操作上都快。选择一种结构就是选择哪些操作应该开销小。它们的开销用大 O 表示,其中 n 为项目数。

两个基本的构件是数组和链表。

a7[0]3[1]9[2]4[3]7394∅h

数组把项目存储在一整块内存里,一个接一个。计算机可以算出第 i 个项目在哪里,所以读取 a[i] 只需 O(1)。在前面插入意味着移动每一个项目:O(n)。

链表把每个项目存储在一个节点里,节点带有指向下一个节点的指针。最后一个指针为 null。在头部(h)插入只改变一个指针:O(1)。但要到达第 i 个项目,你必须沿着 i 个指针走:O(n)。

双向链表还带有指向前一个节点的指针,所以你可以双向行走。

自测 哪个操作对数组是 O(1),而对单向链表是 O(n)?
  1. 在最前面插入一个新项目
  2. 访问每个项目一次
  3. 读取下标 i 处的项目
  4. 逐个数项目的个数

答案: 读取下标 i 处的项目. 数组直接算出第 i 个项目的地址。链表必须从头部沿着 i 个指针走。在最前面插入则正好相反:对链表开销小,对数组开销大。

2栈和队列

栈像一摞盘子:你只在顶部添加和移除。最后进入的项目最先出来:LIFO(后进先出)。

  • push 把一个项目放在顶部,pop 移除顶部的项目,peek 读取顶部而不移除它。它们都是 O(1)。
  • 用途:编辑器的撤销功能、程序的调用栈、检查括号是否匹配、深度优先搜索。

队列像收银台前的队伍:你在队尾加入,在队首离开。最先进入的项目最先出来:FIFO(先进先出)。

  • enqueue 在队尾添加,dequeue 从队首移除。两者都是 O(1)。
  • 用途:打印任务、等待处理的消息、广度优先搜索。

双端队列(deque)允许在两端添加和移除。优先队列总是先移除优先级最高的项目;它通常用堆来实现。

自测 哪种数据结构最适合文本编辑器的“撤销”按钮?
  1. 哈希表
  2. 图
  3. 栈
  4. 队列

答案: 栈. 撤销必须先撤销最近的操作:后进先出。队列会先撤销最早的操作。

3树、堆、哈希表和图

树有一个最顶端的节点,即根。其他每个节点恰好有一个父节点。没有子节点的节点是叶子。有 n 个节点的树有 n − 1 条边。

在二叉树中,每个节点最多有两个子节点。二叉搜索树(BST)增加了一条规则:左子树中的键比该节点小,右子树中的键比它大。

在 BST 中查找沿着一条路径向下,所以开销是 O(高度)。平衡树(AVL、红黑树)使高度保持在 log₂ n 附近。按排序顺序插入键会形成高度为 n 的链。

堆是一种二叉树,其中每个父节点都比它的子节点小(最小堆)或大(最大堆)。最小值或最大值在根处,插入和移除的开销为 O(log n)。

哈希表存储键值对。哈希函数把键变成下标,所以插入和查找平均只需 O(1)。两个键得到同一个下标称为冲突,用链地址法(每个槽一个链表)或开放寻址法(尝试另一个槽)解决。

图有由边连接的顶点,边可以有方向或权重。它可以存为邻接矩阵(O(V²) 内存),或邻接表(O(V + E))。

自测 键 50、30、70、20 和 40 按此顺序插入一棵空的二叉搜索树。30 的左子节点是什么?
  1. 20
  2. 40
  3. 70
  4. 它没有左子节点

答案: 20. 20 比 50 小,所以它向左到 30。它也比 30 小,所以再向左。40 比 30 大,成为它的右子节点。

4分步方法

题目常常描述一个任务,问哪种结构合适,或者问某些操作之后结构是什么样子。

  1. 找出必须快的操作:按位置访问、按键访问、最新的项目、最旧的项目、最小的项目,或一个范围。
  2. 把它与某种结构对应起来:下标 → 数组,键 → 哈希表,最新 → 栈,最旧 → 队列,最小或最大 → 堆,有序或范围 → 平衡搜索树。
  3. 检查任务所需的其他操作的开销,用大 O 表示。
  4. 对于跟踪题,一次执行一个操作,并写下每一步之后的状态。
  5. 用该结构的规则检查最终状态:LIFO、FIFO、BST 的顺序或堆的顺序。

5例题讲解

跟着每一步走。打开下一步之前,先试着预测它。

例题讲解

键 50、30、70、20、40 和 60 按此顺序插入一棵空的二叉搜索树。中序遍历的结果是什么?查找 60 需要多少次比较?

1

插入根

第一个键 50 成为根。

2

插入 30 和 70

30 比 50 小,所以放在左边。70 比 50 大,所以放在右边。

503070
3

插入 20、40 和 60

20:比 50 小,比 30 小,所以在 30 的左边。40:比 50 小,比 30 大,所以在 30 的右边。60:比 50 大,比 70 小,所以在 70 的左边。

503070204060
4

中序遍历

中序遍历先访问左子树,然后是该节点,再是右子树。

这得到 20、30、40、50、60、70:键按排序顺序排列,BST 总是如此。

5

查找 60

与 50 比较:更大,向右。与 70 比较:更小,向左。与 60 比较:找到了。

503070204060

查找需要 3 次比较,每层一次。

答案

中序:20, 30, 40, 50, 60, 70。查找 60 需要 3 次比较。

6常见错误

  • 混淆 LIFO 和 FIFO。栈返回最新的项目,队列返回最旧的。
  • 以为链表可以按下标快速访问。它必须从头部走起。
  • 以为 BST 总是 O(log n)。只有平衡树才是;按排序顺序插入会得到 O(n)。
  • 忘了哈希表中的冲突。O(1) 是平均情况,不是最坏情况。
  • 混淆各种遍历。先序:节点在最前。中序:节点在中间。后序:节点在最后。
  • 对大型稀疏图使用邻接矩阵。这会浪费 O(V²) 的内存。
自测 你按顺序把 1、2 和 3 依次入队到一个空队列。第一次出队返回哪个项目?
  1. 1
  2. 1、2 和 3 一起
  3. 2
  4. 3

答案: 1. 队列是先进先出,所以 1 最先离开。3 是栈(pop)的答案,栈返回最新的项目。

7考试题是什么样的

  • 简单:关键术语和事实。LIFO 和 FIFO,什么是节点、根或叶子,BST 的规则,哈希函数的作用。
  • 中等:应用概念。哪种结构适合某项任务、push 和 pop 或 BST 插入的结果、树的遍历、使用线性探测的哈希表、用大 O 表示的开销。
  • 困难:案例与分析。平衡树、数组中的堆、B 树、字典树、并查集、布隆过滤器,以及 LRU 缓存之类的设计。

对于从下标 0 开始存放在数组中的堆,下标 i 的子节点在 2i + 1 和 2i + 2,它的父节点在 ⌊(i − 1) / 2⌋。

在应用中一步一步地学在应用中一步一步地学

例题

例题 1简单

静态数组与动态数组的主要区别是什么?

  1. A静态数组的下标访问更慢
  2. B动态数组可以通过移到更大的内存块来增长
  3. C动态数组把元素存储在链接的节点中,因此可以一次增长一个
  4. D静态数组只能存储数字
显示提示
  1. Python 的 list 和 Java 的 ArrayList 都是其中一种的例子。
  2. 两个错误答案已被划掉。剩下的两个中有一个是正确的。
显示答案和解析

为什么是这个答案

静态数组大小固定;动态数组在满时分配一个更大的数组并把元素复制过去。

答案

B · 动态数组可以通过移到更大的内存块来增长
例题 2中等

在二叉最小堆中,extract-min 是如何工作的?

  1. A删除数组的最后一个元素
  2. B把最后一个元素移到根上,再将其下沉
  3. C删除根,并把所有元素左移一位
  4. D在所有叶子中查找新的最小值
显示提示
  1. 先保持树的完全性,再修正顺序。
  2. 两个错误答案已被划掉。剩下的两个中有一个是正确的。
显示答案和解析

为什么是这个答案

最后一个元素填补根上的空位,并与其较小的子节点交换,直到满足堆性质,耗时 O(log n)。

答案

B · 把最后一个元素移到根上,再将其下沉
例题 3困难

在没有按秩合并和路径压缩的情况下,含 n 个元素的并查集结构中一次 find 操作的最坏代价是多少?

  1. AO(1)
  2. BO(α(n))
  3. CO(log n)
  4. DO(n)
显示提示
  1. 树可能会退化。
  2. 两个错误答案已被划掉。剩下的两个中有一个是正确的。
显示答案和解析

为什么是这个答案

朴素的合并可能把树连成一条长链,因此 find 可能要沿着 n − 1 个父指针走;这两种启发式方法使其接近常数。

答案

D · O(n)

问与答

什么是数据结构?

没有哪种结构在所有操作上都快。选择一种结构就是选择哪些操作应该开销小。它们的开销用大 O 表示,其中 n 为项目数。

两个基本的构件是数组和链表。

如何一步步学习数据结构?
  1. 什么是数据结构
  2. 栈和队列
  3. 树、堆、哈希表和图
  4. 分步方法
  5. 例题讲解
  6. 常见错误
  7. 考试题是什么样的
数据结构练习包括哪些内容?
  • 简单: 关键术语与事实
  • 中等: 概念应用
  • 困难: 案例与分析

每道题有四个选项,只有一个正确。 卡住了?先打开一个小提示,需要时再查看完整解析。

练习方式

  • 每道题有四个选项,只有一个正确。
  • 卡住了?先打开一个小提示,需要时再查看完整解析。
  • 你的进度、错题和收藏的题目都会保留,方便考前复习。

本主题的前后主题

先学习

包含此主题的课程

计算机科学中的更多主题

可打印练习卷

免费练习数据结构立即练习数据结构每天 5 道免费题目,无需绑定银行卡。