林老师 · 客观题题库 · 第 20 章 堆排序与二叉堆 · 知识细节练习

第 20 章 堆排序与二叉堆 · 知识细节练习

100 题 · 每题对应一个知识细节 · 全部原创
真题
复刻
试卷编号ORIG-第20章堆排序与二叉堆-知识细节练习
题目总数100 题 · 100 分
试卷类型客观题
考生须知:
① 本卷共 16 大部分,合计 100 题 · 100 分,全部为客观题;
② 试卷右上角设有 「提交答卷」「重置考试」 按钮,提交后系统自动判分并显示答题正确情况,请确认全部作答后再行提交;
③ 试卷不显示答案,提交后方可查看每题作答与正确答案的对照;
④ 答卷进度会保留在本地缓存中,刷新或再次打开仍可继续作答;
⑤ 本卷仅供学生练习使用;请勿用于其他用途;题面有问题请联系:i64coder@163.com。

判 分 报 告

0 / 100 分
0
答 对 · 得 0
0
答 错 · 失 0
当前筛选下没有题目

堆的定义与性质

6 QUESTIONS · 2 POINTS EACH
第 1 题 A1 未作答

二叉堆的定义是?

(1 分)
第 2 题 A2 未作答

大根堆中,最大值的位置是?

(1 分)
第 3 题 A3 未作答

堆用数组存储(下标从 1 开始),节点 ii 的左孩子、右孩子、父节点的下标分别是?

(1 分)
第 4 题 A4 未作答

判断题:大根堆中序遍历的结果一定是从小到大有序的——因为堆也是一种"排序树"。

(1 分)
第 5 题 A5 未作答

nn 个节点的完全二叉树(堆)的高度约为?

(1 分)
第 6 题 A6 未作答

判断题:对同一组元素,堆的形态是唯一的。

(1 分)

上浮与下沉

7 QUESTIONS · 2 POINTS EACH
第 7 题 B1 未作答

堆的「上浮」操作用于?

(1 分)
第 8 题 B2 未作答

堆的「下沉」操作用于?

(1 分)
第 9 题 B3 未作答

大根堆删除堆顶(最大值)的标准步骤是?

(1 分)
第 10 题 B4 未作答

大根堆插入新元素的标准步骤是?

(1 分)
第 11 题 B5 未作答

堆的上浮与下沉操作的单次时间复杂度是?

(1 分)
第 12 题 B6 未作答

大根堆下沉时,节点应与哪个孩子交换?

(1 分)
第 13 题 B7 未作答

判断题:堆支持的操作中,「插入」「删除堆顶」都能在 O(logn)O(\log n) 内完成,且「取堆顶(不删除)」只需 O(1)O(1)

(1 分)

建堆

7 QUESTIONS · 2 POINTS EACH
第 14 题 C1 未作答

逐个插入建堆:把 nn 个元素依次插入空堆,每次上浮,总复杂度是?

(1 分)
第 15 题 C2 未作答

自底向上建堆:从最后一个非叶节点开始,逐个下沉,总复杂度是?

(1 分)
第 16 题 C3 未作答

nn 个元素(下标 1~n)自底向上建堆,应从哪个节点开始下沉?

(1 分)
第 17 题 C4 未作答

判断题:自底向上建堆 O(n)O(n) 的直觉是——堆中大部分节点是叶子(下沉 0 层)、倒数第二层节点下沉 1 层……各层节点数 × 下沉深度求和是 O(n)O(n) 级别,而非 n×lognn \times \log n

(1 分)
第 18 题 C5 未作答

逐个插入建堆与自底向上建堆的正确对比是?

(1 分)
第 19 题 C6 未作答

对数组 {3, 1, 2} 自底向上建大根堆(下标 1 起),建堆后的数组是?

(1 分)
第 20 题 C7 未作答

判断题:建堆完成后,数组整体是升序排列的。

(1 分)

堆排序

7 QUESTIONS · 2 POINTS EACH
第 21 题 D1 未作答

堆排序的两大步是?

(1 分)
第 22 题 D2 未作答

堆排序每取出一个堆顶(最大值)后,如何维护剩余堆?

(1 分)
第 23 题 D3 未作答

堆排序的时间复杂度是?

(1 分)
第 24 题 D4 未作答

判断题:堆排序是不稳定排序。

(1 分)
第 25 题 D5 未作答

判断题:堆排序是原地排序——除常数个变量外不需要额外数组(O(1)O(1) 额外空间)。

(1 分)
第 26 题 D6 未作答

{4, 1, 3, 2} 建大根堆后(下标 1 起,自底向上建堆),堆顶与末尾交换、缩堆、下沉——第一轮之后数组(前 3 位为堆、末位为已就位最大值)是?

(1 分)
第 27 题 D7 未作答

要把数组排成升序,堆排序应建哪种堆?

(1 分)

优先队列

6 QUESTIONS · 2 POINTS EACH
第 28 题 E1 未作答

优先队列与普通队列的区别是?

(1 分)
第 29 题 E2 未作答

C++ 中 priority_queue<int> 默认是?

(1 分)
第 30 题 E3 未作答

C++ 中声明小根堆 priority_queue 的正确写法是?

(1 分)
第 31 题 E4 未作答

下列哪个场景最适合用优先队列?

(1 分)
第 32 题 E5 未作答

判断题:手写二叉堆与 STL priority_queue 的功能等价——手写更灵活(支持删除任意元素/修改值),STL 更省事且不易写错。

(1 分)
第 33 题 E6 未作答

只需「每次都取当前最大值、过程中不断插入」的场景(数据流式),选哪种结构最合适?

(1 分)

堆的应用与变体

6 QUESTIONS · 2 POINTS EACH
第 34 题 F1 未作答

「对顶堆」求动态中位数的结构是?

(1 分)
第 35 题 F2 未作答

nn 个数中最大的 kk 个(knk \ll n),用堆的做法是?

(1 分)
第 36 题 F3 未作答

多路归并(合并 mm 个有序序列)用小根堆的作用是?

(1 分)
第 37 题 F4 未作答

判断题:栈是 LIFO、队列是 FIFO、堆是「按优先级出」——三者存取顺序规则完全不同。

(1 分)
第 38 题 F5 未作答

构造哈夫曼树(合并果子问题)时每次取两个最小权值合并,常用结构是?

(1 分)
第 39 题 F6 未作答

判断题:数组 {50, 30, 40, 10, 20}(下标 1 起)满足大根堆的堆序。

(1 分)

复杂度与对比

6 QUESTIONS · 2 POINTS EACH
第 40 题 G1 未作答

下列关于堆排序、快速排序与归并排序的复杂度、空间与稳定性,说法正确的是?( )

(1 分)
第 41 题 G2 未作答

堆的三种操作——插入、删除堆顶、取堆顶(不删除)的复杂度分别是?

(1 分)
第 42 题 G3 未作答

判断题:自底向上建堆 O(n)O(n) 优于逐个插入建堆 O(nlogn)O(n \log n),因此工程中建堆都用自底向上。

(1 分)
第 43 题 G4 未作答

判断题:堆排序虽然复杂度是 O(nlogn)O(n \log n),但实际常比快排慢——因为下沉过程数据跳跃访问、缓存不友好,且常数因子较大。

(1 分)
第 44 题 G5 未作答

判断题:堆排序不稳定,归并排序稳定,快速排序不稳定——三者中只有归并稳定。

(1 分)
第 45 题 G6 未作答

内存极紧张(几乎无额外空间可用)、需要 O(nlogn)O(n \log n) 排序,选哪种?

(1 分)

易错综合

5 QUESTIONS · 2 POINTS EACH
第 46 题 H1 未作答

判断题:大根堆只保证"父 \ge 子"的局部关系,中序遍历堆并不得到有序序列。

(1 分)
第 47 题 H2 未作答

大根堆下沉时,若节点与较小的孩子交换(而非较大的),后果是?

(1 分)
第 48 题 H3 未作答

判断题:自底向上建堆从 i=1i = 1(根)开始向下逐层下沉也能正确建堆。

(1 分)
第 49 题 H4 未作答

判断题:把大根堆的上浮/下沉比较条件(><)全部取反,就得到小根堆的实现。

(1 分)
第 50 题 H5 未作答

判断题:以下结论全部正确——"堆是完全二叉树的数组实现;建堆 O(n)O(n);堆排序 O(nlogn)O(n \log n) 且不稳定;priority_queue 默认大根堆"。

(1 分)

堆存储与性质代码

6 QUESTIONS · 2 POINTS EACH
第 51 题 I1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    int i = 3;                 // 堆数组下标从 1 起
05    cout << i / 2 << " " << 2 * i << " " << 2 * i + 1;
06    return 0;
07}

单选题:程序输出是?(节点 3 的父、左孩子、右孩子下标)

(1 分)
第 52 题 I2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    int a[6] = {0, 50, 30, 40, 10, 20};   // 下标 1~5,a[0] 占位
05    bool ok = true;
06    for (int i = 1; i <= 2; i++)          // 只检查非叶节点 1、2
07        for (int j = 2 * i; j <= 2 * i + 1 && j <= 5; j++)
08            if (a[i] < a[j]) ok = false;
09    cout << (ok ? "YES" : "NO");
10    return 0;
11}

单选题:程序输出是?(该数组是否为大根堆)

(1 分)
第 53 题 I3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0, 10, 8, 7, 3, 5};   // 小根堆,下标 1 起
04int main() {
05    // 输出按层:根 / 左子-右子 / 左子-右子-左子-右子
06    for (int i = 1; i <= 5; i++) cout << a[i] << " ";
07    return 0;
08}

单选题:程序输出是?(按完全二叉树层序读出的堆)

(1 分)
第 54 题 I4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0, 50, 30, 40, 10, 20};   // 大根堆
04int main() {
05    cout << a[1];                      // 取堆顶(不删除)
06    return 0;
07}

单选题:程序输出是?

(1 分)
第 55 题 I5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    int a[6] = {0, 1, 3, 2, 5, 4};   // 下标 1~5
05    bool minH = true, maxH = true;
06    for (int i = 1; i <= 2; i++)
07        for (int j = 2 * i; j <= 2 * i + 1 && j <= 5; j++) {
08            if (a[i] > a[j]) minH = false;
09            if (a[i] < a[j]) maxH = false;
10        }
11    cout << (minH ? "MIN" : (maxH ? "MAX" : "NEITHER"));
12    return 0;
13}

单选题:程序输出是?

(1 分)
第 56 题 I6 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    int n = 7;
05    int h = 0;
06    while (n) { n /= 2; h++; }    // 每次去掉一层
07    cout << h;
08    return 0;
09}

单选题:程序输出是?(7 个节点的完全二叉树的高度,即根到最深叶的层数)

(1 分)

上浮下沉代码

6 QUESTIONS · 2 POINTS EACH
第 57 题 J1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[7] = {0, 9, 7, 8, 3, 1};   // 大根堆,下标 1~5
04int sz = 5;
05void up(int i) {
06    while (i > 1 && a[i] > a[i / 2]) {
07        swap(a[i], a[i / 2]);
08        i /= 2;
09    }
10}
11int main() {
12    a[++sz] = 10;                // 插入 10
13    up(sz);
14    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
15    return 0;
16}

单选题:程序输出是?(插入 10 并上浮后的堆)

(1 分)
第 58 题 J2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0, 3, 7, 8, 9, 5};   // 下标 1~5,仅堆顶 3 破坏堆序
04int sz = 5;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;                    // 左孩子
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;   // 取较大孩子
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    down(1);
16    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
17    return 0;
18}

单选题:程序输出是?(堆顶下沉修复后的堆)

(1 分)
第 59 题 J3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[7] = {0, 10, 5, 8, 3, 1};   // 大根堆
04int sz = 5;
05void up(int i) {
06    while (i > 1 && a[i] > a[i / 2]) { swap(a[i], a[i / 2]); i /= 2; }
07}
08int main() {
09    a[++sz] = 9;                 // 插入 9
10    up(sz);
11    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
12    return 0;
13}

单选题:程序输出是?

(1 分)
第 60 题 J4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0, 10, 7, 9, 3, 1};   // 大根堆
04int sz = 5;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    a[1] = a[sz--];              // 末元素移到堆顶,删除堆顶
16    down(1);
17    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
18    return 0;
19}

单选题:程序输出是?(删除堆顶 10 后的堆)

(1 分)
第 61 题 J5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[7] = {0, 9, 7, 8, 3, 1, 10};   // 刚插入 10(末尾)
04int sz = 6;
05void up(int i) {
06    while (______) {                  // 未到根且大于父
07        swap(a[i], a[i / 2]);
08        i /= 2;
09    }
10}
11int main() { up(6); cout << a[1]; return 0; }

单选题:横线处应填入?(使输出为 10——10 上浮到堆顶)

(1 分)
第 62 题 J6 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0, 3, 7, 8, 9, 5};   // 大根堆待修复
04int sz = 5;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (______) j++;          // 右孩子更大时选右孩子
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() { down(1); cout << a[1]; return 0; }

单选题:横线处应填入?(使输出为 8——堆顶 3 与较大的孩子 8 交换)

(1 分)
拾壹

建堆代码

7 QUESTIONS · 2 POINTS EACH
第 63 题 K1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};   // 下标 1~4
04int sz = 4;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = sz / 2; i >= 1; i--) down(i);   // 自底向上建堆
16    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
17    return 0;
18}

单选题:程序输出是?(自底向上建出的大根堆)

(1 分)
第 64 题 K2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    int n = 5;
05    cout << n / 2;         // 自底向上建堆的起始下标
06    return 0;
07}

单选题:程序输出是?(5 个元素自底向上建堆,第一个下沉的节点下标)

(1 分)
第 65 题 K3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0};   // 下标 1 起
04int sz = 0;
05void up(int i) {
06    while (i > 1 && a[i] > a[i / 2]) { swap(a[i], a[i / 2]); i /= 2; }
07}
08int main() {
09    int d[4] = {4, 1, 3, 2};
10    for (int k = 0; k < 4; k++) { a[++sz] = d[k]; up(sz); }   // 逐个插入
11    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
12    return 0;
13}

单选题:程序输出是?(逐个插入建出的大根堆)

(1 分)
第 66 题 K4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4, cnt = 0;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]); cnt++;
11        i = j;
12    }
13}
14int main() {
15    for (int i = sz / 2; i >= 1; i--) down(i);
16    cout << cnt;
17    return 0;
18}

单选题:程序输出是?(对 {4, 1, 3, 2} 自底向上建堆的交换次数)

(1 分)
第 67 题 K5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = ______; i >= 1; i--) down(i);   // 自底向上建堆
16    cout << a[1];
17    return 0;
18}

单选题:横线处应填入?(使输出为 4——建成大根堆后堆顶)

(1 分)
第 68 题 K6 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (______) break;          // 堆序已满足
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = sz / 2; i >= 1; i--) down(i);
16    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
17    return 0;
18}

单选题:横线处应填入?(使输出为 4 2 3 1

(1 分)
第 69 题 K7 未作答

01#include <bits/stdc++.h>
02using namespace std;
03// 建堆 A:逐个插入(up);建堆 B:自底向上(down)
04// 对输入 {1, 5, 2, 3, 4}:A 得到 {5, 4, 2, 1, 3},B 得到 {5, 4, 2, 3, 1}
05int main() {
06    int x[6] = {0, 5, 4, 2, 1, 3};   // 建堆 A 的结果
07    int y[6] = {0, 5, 4, 2, 3, 1};   // 建堆 B 的结果
08    cout << x[5] << " " << y[5];
09    return 0;
10}

判断题:对同一组输入,逐个插入建堆与自底向上建堆得到的堆不一定相同——但两者都是合法的大根堆(堆形态不唯一)。

(1 分)
拾贰

堆排序代码

6 QUESTIONS · 2 POINTS EACH
第 70 题 L1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};   // 下标 1 起
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = sz / 2; i >= 1; i--) down(i, sz);     // 建堆
16    for (int n = sz; n > 1; n--) {                     // 反复取顶
17        swap(a[1], a[n]);
18        down(1, n - 1);
19    }
20    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
21    return 0;
22}

单选题:程序输出是?

(1 分)
第 71 题 L2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 2, 3, 1};   // 已是大根堆
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int n = sz; n >= 1; n--) {
16        cout << a[1] << " ";          // 输出当前堆顶
17        swap(a[1], a[n]);
18        down(1, n - 1);
19    }
20    return 0;
21}

单选题:程序输出是?(每次输出的堆顶序列,即从大到小)

(1 分)
第 72 题 L3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 2, 3, 1};   // 大根堆
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    ______;              // 堆顶(最大值)与当前堆末尾交换
16    cout << a[4];
17    return 0;
18}

单选题:横线处应填入?(使输出为 4——最大值已移到末位)

(1 分)
第 73 题 L4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 2, 3, 1};
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    swap(a[1], a[sz]);
16    ______;              // 堆缩小
17    down(1, sz);
18    cout << a[1] << " " << a[2] << " " << a[3];
19    return 0;
20}

单选题:横线处应填入?(使输出为 3 2 1——缩小并下沉后的堆)

(1 分)
第 74 题 L5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = sz / 2; i >= 1; i--) down(i, sz);
16    for (int n = sz; n > 1; n--) { swap(a[1], a[n]); down(1, n - 1); }
17    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
18    return 0;
19}

判断题:该程序建大根堆做堆排序,输出是升序 1 2 3 4——升序排序要用大根堆,因为最大值先就位到末尾。

(1 分)
第 75 题 L6 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4, cnt = 0;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]); cnt++;
11        i = j;
12    }
13}
14int main() {
15    for (int i = sz / 2; i >= 1; i--) down(i, sz);
16    for (int n = sz; n > 1; n--) { swap(a[1], a[n]); cnt++; down(1, n - 1); }
17    cout << cnt;
18    return 0;
19}

单选题:程序输出是?(建堆 + 堆排序全程的交换次数)

(1 分)
拾叁

优先队列代码

6 QUESTIONS · 2 POINTS EACH
第 76 题 M1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    priority_queue<int> q;             // 默认大根堆
05    int d[5] = {3, 1, 4, 1, 5};
06    for (int i = 0; i < 5; i++) q.push(d[i]);
07    while (!q.empty()) { cout << q.top() << " "; q.pop(); }
08    return 0;
09}

单选题:程序输出是?

(1 分)
第 77 题 M2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    priority_queue<int, vector<int>, greater<int>> q;   // 小根堆
05    int d[5] = {3, 1, 4, 1, 5};
06    for (int i = 0; i < 5; i++) q.push(d[i]);
07    while (!q.empty()) { cout << q.top() << " "; q.pop(); }
08    return 0;
09}

单选题:程序输出是?

(1 分)
第 78 题 M3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    priority_queue<int> q;
05    q.push(3); q.push(1); q.push(4);
06    cout << q.top() << " "; q.pop();     // 取走当前最大
07    q.push(2);
08    cout << q.top() << " "; q.pop();
09    cout << q.top() << " "; q.pop();
10    cout << q.top() << " "; q.pop();
11    return 0;
12}

单选题:程序输出是?

(1 分)
第 79 题 M4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    int h[5] = {0};        // 手写小根堆,下标 1 起
05    int sz = 0;
06    auto up = [&](int i) { while (i > 1 && h[i] < h[i / 2]) { swap(h[i], h[i / 2]); i /= 2; } };
07    int d[4] = {3, 1, 4, 2};
08    for (int k = 0; k < 4; k++) { h[++sz] = d[k]; up(sz); }
09    cout << h[1] << " ";   // 手写堆顶(最小)
10    priority_queue<int, vector<int>, greater<int>> q;
11    for (int k = 0; k < 4; k++) q.push(d[k]);
12    cout << q.top();       // STL 堆顶(最小)
13    return 0;
14}

单选题:程序输出是?

(1 分)
第 80 题 M5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03struct cmp {                        // 自定义比较:a 优先于 b 当 a > b
04    bool operator()(int a, int b) { return a > b; }
05};
06int main() {
07    priority_queue<int, vector<int>, cmp> q;   // 小根堆
08    int d[3] = {3, 1, 2};
09    for (int i = 0; i < 3; i++) q.push(d[i]);
10    while (!q.empty()) { cout << q.top() << " "; q.pop(); }
11    return 0;
12}

单选题:程序输出是?

(1 分)
第 81 题 M6 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    int d[8] = {3, 1, 4, 1, 5, 9, 2, 6};
05    int k = 3;
06    priority_queue<int, vector<int>, greater<int>> q;   // 大小为 k 的小根堆
07    for (int i = 0; i < 8; i++) {
08        if ((int)q.size() < k) q.push(d[i]);
09        else if (d[i] > q.top()) { q.pop(); q.push(d[i]); }
10    }
11    // 堆内是最大的 k 个(升序输出)
12    int out[3], t = 0;
13    while (!q.empty()) { out[t++] = q.top(); q.pop(); }
14    for (int i = t - 1; i >= 0; i--) cout << out[i] << " ";
15    return 0;
16}

单选题:程序输出是?(8 个数中最大的 3 个,降序)

(1 分)
拾肆

堆应用代码

6 QUESTIONS · 2 POINTS EACH
第 82 题 N1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    // 对顶堆:maxh 存较小一半(大根堆),minh 存较大一半(小根堆)
05    priority_queue<int> maxh;
06    priority_queue<int, vector<int>, greater<int>> minh;
07    int d[5] = {5, 2, 8, 1, 9};
08    for (int i = 0; i < 5; i++) {
09        int x = d[i];
10        if (maxh.empty() || x <= maxh.top()) maxh.push(x);
11        else minh.push(x);
12        // 平衡:maxh 大小至多比 minh 大 1
13        if ((int)maxh.size() > (int)minh.size() + 1) { minh.push(maxh.top()); maxh.pop(); }
14        if ((int)minh.size() > (int)maxh.size()) { maxh.push(minh.top()); minh.pop(); }
15    }
16    cout << maxh.top();    // 中位数(maxh 存较小一半,堆顶为其中最大)
17    return 0;
18}

单选题:程序输出是?(序列 {5, 2, 8, 1, 9} 的中位数)

(1 分)
第 83 题 N2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    priority_queue<int, vector<int>, greater<int>> q;   // 小根堆
05    int d[3] = {1, 2, 9};
06    for (int i = 0; i < 3; i++) q.push(d[i]);
07    int cost = 0;
08    while (q.size() > 1) {
09        int a = q.top(); q.pop();
10        int b = q.top(); q.pop();
11        cost += a + b;                 // 合并代价
12        q.push(a + b);                 // 合并结果放回
13    }
14    cout << cost;
15    return 0;
16}

单选题:程序输出是?(合并果子最小总代价:先 1+2=3,再 3+9=12)

(1 分)
第 84 题 N3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    // 排队接水:n 个人用时 a[i],按用时从小到大排队,求总等待时间
05    priority_queue<int, vector<int>, greater<int>> q;
06    int d[3] = {3, 1, 2};
07    for (int i = 0; i < 3; i++) q.push(d[i]);
08    long long wait = 0, cur = 0;
09    while (!q.empty()) {
10        cur += q.top(); q.pop();   // cur = 该人完成时刻
11        wait += cur;               // 累计所有人的完成时刻之和
12    }
13    cout << wait;
14    return 0;
15}

单选题:程序输出是?(总等待 = 完成时刻 1 + 3 + 6)

(1 分)
第 85 题 N4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    // 三路归并:三个有序序列的头元素入堆,每次取最小
05    int s[3][3] = {{1, 4, 7}, {2, 5, 8}, {3, 6, 9}};
06    int p[3] = {0, 0, 0};
07    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
08    for (int i = 0; i < 3; i++) q.push({s[i][0], i});
09    while (!q.empty()) {
10        auto cur = q.top(); q.pop();
11        cout << cur.first << " ";
12        int id = cur.second;
13        if (++p[id] < 3) q.push({s[id][p[id]], id});
14    }
15    return 0;
16}

单选题:程序输出是?

(1 分)
第 86 题 N5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[7] = {0, 9, 7, 8, 3, 1};   // 大根堆
04int sz = 5;
05void up(int i) { while (i > 1 && a[i] > a[i / 2]) { swap(a[i], a[i / 2]); i /= 2; } }
06void down(int i) {
07    while (2 * i <= sz) {
08        int j = 2 * i;
09        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
10        if (a[i] >= a[j]) break;
11        swap(a[i], a[j]);
12        i = j;
13    }
14}
15int main() {
16    a[++sz] = 12; up(sz);          // 插入 12
17    a[1] = a[sz--]; down(1);       // 删除堆顶(12)
18    a[++sz] = 5; up(sz);           // 插入 5
19    cout << a[1] << " " << a[2] << " " << a[3];
20    return 0;
21}

单选题:程序输出是?

(1 分)
第 87 题 N6 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0};   // 大根堆,下标 1 起
04int sz = 0;
05void up(int i) { while (i > 1 && a[i] > a[i / 2]) { swap(a[i], a[i / 2]); i /= 2; } }
06int main() {
07    int op[5] = {2, 7, 1, 3, 5};   // 依次插入
08    for (int k = 0; k < 5; k++) { a[++sz] = op[k]; up(sz); }
09    cout << a[1] << " " << a[2] << " " << a[3] << " " << a[4] << " " << a[5];
10    return 0;
11}

单选题:程序输出是?(依次插入 2、7、1、3、5 后的堆)

(1 分)
拾伍

完善程序

7 QUESTIONS · 2 POINTS EACH
第 88 题 O1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[7] = {0, 9, 7, 8, 3, 1, 10};   // 刚插入 10
04int sz = 6;
05void up(int i) {
06    while (i > 1 && a[i] > a[i / 2]) {
07        ______;                  // 与父节点交换
08        i /= 2;
09    }
10}
11int main() { up(6); for (int i = 1; i <= sz; i++) cout << a[i] << " "; return 0; }

单选题:横线处应填入?(使输出为 10 7 9 3 1 8

(1 分)
第 89 题 O2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0, 3, 7, 8, 9, 5};
04int sz = 5;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        ______;                  // 继续向下
12    }
13}
14int main() { down(1); for (int i = 1; i <= sz; i++) cout << a[i] << " "; return 0; }

单选题:横线处应填入?(使输出为 8 7 3 9 5

(1 分)
第 90 题 O3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = ______; i >= 1; i--) down(i);   // 自底向上建堆
16    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
17    return 0;
18}

单选题:横线处应填入?(使输出为 4 2 3 1

(1 分)
第 91 题 O4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 2, 3, 1};
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int n = sz; n > 1; n--) {
16        swap(a[1], a[n]);
17        ______;                  // 对缩小后的堆做下沉
18    }
19    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
20    return 0;
21}

单选题:横线处应填入?(使输出为 1 2 3 4

(1 分)
第 92 题 O5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03priority_queue<int> maxh;                                    // 较小一半
04priority_queue<int, vector<int>, greater<int>> minh;         // 较大一半
05void add(int x) {
06    if (maxh.empty() || x <= maxh.top()) maxh.push(x);
07    else minh.push(x);
08    if ((int)maxh.size() > (int)minh.size() + 1) { minh.push(maxh.top()); maxh.pop(); }
09    if (______) { maxh.push(minh.top()); minh.pop(); }       // 平衡:较小一半不可少于较大一半
10}
11int main() {
12    int d[5] = {5, 2, 8, 1, 9};
13    for (int i = 0; i < 5; i++) add(d[i]);
14    cout << maxh.top();
15    return 0;
16}

单选题:横线处应填入?(使输出为 5——动态中位数)

(1 分)
第 93 题 O6 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    priority_queue<int, vector<int>, greater<int>> q;
05    int d[3] = {1, 2, 9};
06    for (int i = 0; i < 3; i++) q.push(d[i]);
07    int cost = 0;
08    while (q.size() > 1) {
09        int a = q.top(); q.pop();
10        int b = q.top(); q.pop();
11        ______;                  // 累计合并代价并放回
12        q.push(a + b);
13    }
14    cout << cost;
15    return 0;
16}

单选题:横线处应填入?(使输出为 15

(1 分)
第 94 题 O7 未作答

01#include <bits/stdc++.h>
02using namespace std;
03struct cmp {
04    bool operator()(int a, int b) { return ______; }   // 队首为最小
05};
06int main() {
07    priority_queue<int, vector<int>, cmp> q;
08    q.push(3); q.push(1); q.push(2);
09    cout << q.top();
10    return 0;
11}

单选题:横线处应填入?(使输出为 1

(1 分)
拾陆

代码易错

6 QUESTIONS · 2 POINTS EACH
第 95 题 P1 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[6] = {0, 3, 7, 8, 9, 5};
04int sz = 5;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (______) j++;           // 错误:漏了 j + 1 <= sz 的边界判断
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() { down(1); cout << "run"; return 0; }

单选题:横线处应填入?(使程序在节点无右孩子时可能访问越界——这是下沉的经典 bug)

(1 分)
第 96 题 P2 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] < a[j]) j++;   // 错误:取较小孩子 → 小根堆方向
09        if (a[i] <= a[j]) break;                  // 错误:比较方向反
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = sz / 2; i >= 1; i--) down(i, sz);
16    for (int n = sz; n > 1; n--) { swap(a[1], a[n]); down(1, n - 1); }
17    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
18    return 0;
19}

单选题:程序输出是?(比较方向全反 → 小根堆堆排序)

(1 分)
第 97 题 P3 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 1, 3, 2};
04int sz = 4;
05void down(int i) {
06    while (2 * i <= sz) {
07        int j = 2 * i;
08        if (j + 1 <= sz && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int i = 1; i >= 1; i--) down(i);   // 错误:只从根下沉,叶子层未处理
16    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
17    return 0;
18}

单选题:程序输出是?({4, 1, 3, 2} 中根 4 已是最大、一次下沉都没发生,结果不满足堆序)

(1 分)
第 98 题 P4 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int a[5] = {0, 4, 2, 3, 1};
04int sz = 4;
05void down(int i, int n) {
06    while (2 * i <= n) {
07        int j = 2 * i;
08        if (j + 1 <= n && a[j + 1] > a[j]) j++;
09        if (a[i] >= a[j]) break;
10        swap(a[i], a[j]);
11        i = j;
12    }
13}
14int main() {
15    for (int n = sz; n > 1; n--) {
16        swap(a[1], a[n]);
17        down(1, n);        // 错误:n 未减 1,已就位的元素被拉回堆中
18    }
19    for (int i = 1; i <= sz; i++) cout << a[i] << " ";
20    return 0;
21}

单选题:程序输出是?

(1 分)
第 99 题 P5 未作答

01#include <bits/stdc++.h>
02using namespace std;
03int main() {
04    // 下标从 0 起的堆:节点 i 的孩子与父
05    int i = 2;
06    cout << (i - 1) / 2 << " " << 2 * i + 1 << " " << 2 * i + 2;
07    return 0;
08}

单选题:程序输出是?(下标 0 起时,节点 2 的父、左孩子、右孩子下标)

(1 分)
第 100 题 P6 未作答

判断题:以下结论全部正确——"堆排序原地且 O(nlogn)O(n \log n) 但不稳定;priority_queue 默认大根堆;自底向上建堆 O(n)O(n);对顶堆能动态维护中位数"。

(1 分)