判断题:排序 = 按关键字(数值大小、字典序等)把一组元素重新排列成升序或降序的有序序列。
考点:排序的定义(A1)。
解析:排序 = 按关键字(数值、字典序、优先级等)把一组元素重排成升序或降序。✅ 正确
排除法:无(判断题)。混淆点:排序的对象是"记录",关键字只是排序依据——记录本身要跟着移动。
关联 · 升序与降序(A2):方向由比较符号决定。
单选题:把数组 {3, 1, 4, 1, 5} 排成升序,结果是?
考点:升序与降序(A2)。
解析:升序 = 小的在前:{3,1,4,1,5} → 1 1 3 4 5(相等元素相邻排)。正确答案 A。
排除法:B 是降序;C 是原数组;D 只排了前三个、后两个还是乱序。
关联 · 降序冒泡(I5):把比较方向翻转即可得降序。
判断题:稳定性 = 排序后关键字相等的元素之间的相对先后顺序保持不变。
考点:稳定性的定义(A3)。
解析:稳定性 = 关键字相等的元素排序前后相对顺序不变。例如按"成绩"排序,两个 90 分的同学在名单里的先后不变。✅ 正确
排除法:无(判断题)。混淆点:稳定性只关乎相等元素,与"不相等元素谁前谁后"无关。
关联 · 稳定排序清单(G4):冒泡/插入/归并/计数稳定。
单选题:以下哪个排序算法不基于元素之间的比较?
考点:比较排序与非比较排序(A4)。
解析:冒泡、选择、插入、快排、归并、堆排序都靠"元素两两比较"决定顺序;计数排序统计每个值出现次数、不比较元素。正确答案 C。
排除法:A、B、D 都是比较排序。
关联 · 比较排序的下界(G6):比较排序最坏至少 ,计数排序可 。
单选题:原地排序(in-place)指排序过程的额外空间开销为?
考点:原地排序(A5)。
解析:原地(in-place)= 除输入数组外只使用 额外空间(几个循环变量)。冒泡/选择/插入/堆排序是原地;归并要 辅助数组、不是原地。正确答案 A。
排除法:B 是归并排序的空间;C、D 无对应算法。
关联 · 归并的空间与稳定性(E7): 辅助数组换稳定性。
判断题:评价一个排序算法,通常看三个维度:时间复杂度、空间复杂度、稳定性。
考点:评价排序的维度(A6)。
解析:三大维度:时间复杂度(快不快)、空间复杂度(省不省内存)、稳定性(相等元素次序保不保)。✅ 正确
排除法:无(判断题)。混淆点:常数因子也影响实际速度(插入排序在小数据上比快排快),但复杂度分析是主线。
关联 · 排序算法的选择(G7):按场景选算法,三个维度一起权衡。
判断题:冒泡排序 = 反复比较相邻元素,若逆序就交换,每轮把当前未排部分的最大元素"冒"到末尾。
考点:冒泡的基本思想(B1)。
解析:每轮从前往后比较相邻元素,逆序就交换;一轮结束,当前最大元素"冒"到未排部分的末尾。✅ 正确
排除法:无(判断题)。混淆点:冒泡只交换相邻元素——这正是它稳定的原因(B4)。
关联 · 冒泡第一轮的结果(B2):一轮只保证最大值就位。
单选题:数组 {5, 3, 8, 1, 7} 做冒泡排序的第一轮(从头到尾相邻比较、逆序交换)之后,数组变成?
考点:冒泡第一轮的结果(B2)。
解析:{5,3,8,1,7} 第一轮: 换、 不换、 换、 换 → 3 5 1 7 8,最大 8 已到末尾。正确答案 A。
排除法:B 是完整排序结果;C 是部分反向;D 是只交换了第一对。
关联 · 冒泡两趟后的状态(I6):第 k 轮后末尾 k 个元素就位。
单选题:冒泡排序最好情况(已有序 + 优化版)与最坏情况的时间复杂度分别是?
考点:冒泡的时间复杂度(B3)。
解析:优化版在已有序时一轮无交换即退出 → 最好 ;逆序时比较 。正确答案 A。
排除法:B 把最好情况记成 ;C 忽略了优化;D 把最坏记成 。
关联 · 冒泡的提前结束优化(B5):最好 来自提前退出。
判断题:冒泡排序是稳定的——相等元素不交换,相对顺序保持不变。
考点:冒泡的稳定性(B4)。
解析:相等元素之间不满足 >,不会交换 → 相对顺序不变 → 稳定。✅ 正确
排除法:无(判断题)。混淆点:只要交换条件用 >(或 <)而不是 >=(或 <=),相等就不换。
关联 · 稳定性的判断依据(H1):只交换相邻元素是稳定的常见特征。
判断题:冒泡排序加一个"本轮无交换就提前结束"的标志后,对已有序数组只需一轮 次比较,时间复杂度为 。
考点:冒泡的提前结束优化(B5)。
解析:swapped 标志:一轮中没发生任何交换说明已有序,立即结束。已有序数组只跑 1 轮、比较 次 → 。✅ 正确
排除法:无(判断题)。混淆点:无优化版即使有序也跑满 轮、。
关联 · 冒泡优化的趟数(I4):基本有序数组 2 趟就完成。
单选题: 个元素的数组用冒泡排序(无优化)完全排好序,最多需要几趟?
考点:冒泡的趟数(B6)。
解析:每趟至少就位 1 个元素(最大值), 个元素最多 趟; 时最多 趟。正确答案 A。
排除法:B 多算一趟;C 少算;D 把趟数当成总比较次数。
关联 · 冒泡的趟数(I 组):外层循环
i < n - 1就是趟数。
判断题:选择排序 = 每轮从未排序部分选出最小元素,放到已排序部分的末尾。
考点:选择的基本思想(C1)。
解析:每轮扫描未排序部分找出最小元素,与未排序部分的第一个位置交换 → 放到已排序部分的末尾。✅ 正确
排除法:无(判断题)。混淆点:每轮只做一次"隔空"交换——这是它与冒泡的最大区别(C4)。
关联 · 选择的比较与交换次数(C2):交换 、比较 。
单选题:选择排序对 个元素排序,比较次数和交换次数分别约为?
考点:选择的比较与交换次数(C2)。
解析:比较次数固定 (与输入无关);交换最多 次(每轮至多一次)。正确答案 A。
排除法:B 把交换也记成 ;C/D 张冠李戴。
关联 · 选择的比较次数(J5): 时比较 次。
判断题:选择排序不稳定——例如 {2, 2, 1}(两个 2 值相同)升序排序时,第一轮把 1 与第一个 2 交换,两个 2 的相对顺序被颠倒。
考点:选择的不稳定性(C3)。
解析:{2, 2, 1} 升序:第一轮最小是 1(下标 2),与下标 0 的 2 交换 → 1 2 2,两个 2 的相对顺序颠倒。✅ 正确
排除法:无(判断题)。混淆点:交换跨越了相等元素,就可能破坏稳定。
关联 · 不稳定排序清单(G5):选择是三大不稳定排序之一。
单选题:与冒泡排序相比,选择排序的特点是?
考点:选择与冒泡的对比(C4)。
解析:选择每轮只交换 1 次,总交换 ;冒泡每次逆序都交换,最坏 。比较次数两者都是 。正确答案 A。
排除法:B——比较次数同量级;C——复杂度相同;D——选择不稳定。
关联 · 选择的交换次数(J2):
{5,3,8,1,7}只交换 3 次。
判断题:选择排序第 轮结束后,前 个元素已经就位(就是最终结果的前 个)。
考点:选择第 i 轮就位(C5)。
解析:第 轮把全局第 小的元素放到下标 ,之后不再动 → 前 个元素是最终结果。✅ 正确
排除法:无(判断题)。混淆点:插入排序的前缀只是"暂时有序",会再变(D5)——这是两排序的经典区别。
关联 · 插入的前缀有序(D5):选择"就位"、插入"暂序"。
单选题:选择排序每轮选最小放最前;若改成每轮选最大放最后,排序结果会?
考点:选最大放末尾(C6)。
解析:每轮选最大放到末尾与选最小放最前完全对称,最终同样是升序。正确答案 A。
排除法:B 是"选最大放最前"才会得的降序;C、D 无依据。
关联 · 选最大放末尾(J4):
i从n-1递减,找[0, i]中最大。
判断题:插入排序像打扑克抓牌:每拿到一张新牌(新元素),把它插入到已排好序部分中的正确位置。
考点:插入的基本思想(D1)。
解析:像抓牌:新元素(key)与已有序前缀从右往左比较,比 key 大的后移,key 落位在正确位置。✅ 正确
排除法:无(判断题)。混淆点:插入是"边比较边移动",与选择"先找再换"不同。
关联 · 插入的移动实现(D6):移动就是为 key 腾位置。
单选题:插入排序最好情况(已有序)与最坏情况(完全逆序)的时间复杂度分别是?
考点:插入的时间复杂度(D2)。
解析:已有序时内层 while 一次都不进 → ;逆序时每轮移动 次 → 。正确答案 A。
排除法:B 把最好记成 ;C 忽略最好情况;D 无依据。
关联 · 已有序的移动次数(K5):有序输入移动 0 次。
判断题:插入排序是稳定的——相等元素时新元素插在旧元素后面,不越过它。
考点:插入的稳定性(D3)。
解析:内层条件是 a[j] > key(严格大于),相等元素不移位、key 落在相等元素的后面 → 稳定。✅ 正确
排除法:无(判断题)。混淆点:把条件改成 >= 就破坏稳定性。
关联 · 归并的稳定性细节(M7):合并条件
<=与<的同款细节。
单选题:插入排序最擅长的场景是?
考点:插入的适用场景(D4)。
解析:插入排序在"基本有序"或"数据量小"时表现极佳(移动少、常数小)——这也是快排/归并递归到小区间时切换到插入排序的原因。正确答案 A。
排除法:B 是插入的最坏输入;C 交给 算法;D 与排序无关。
关联 · 排序算法的选择(G7):小数据/基本有序 → 插入。
判断题:插入排序第 轮结束后,前 个元素是有序的(但不一定是最终结果的前 个)——这正是它与选择排序的区别。
考点:插入的前缀有序(D5)。
解析:第 轮后前 个元素有序,但不保证是最终结果——后面更小的元素还会插入到它们前面。✅ 正确
排除法:无(判断题)。混淆点:选择排序第 轮后前 个已就位(C5),插入排序只是暂时有序。
关联 · 选择第 i 轮就位(C5):两排序的前缀性质对比。
单选题:插入排序内层把比 key 大的元素逐个后移,循环结束后把 key 放在哪里?
考点:插入的移动实现(D6)。
解析:内层循环结束时 j 指向第一个 <= key 的位置(或 -1),key 应放在 j + 1。正确答案 A。
排除法:B/C 只在边界巧合;D 无依据。
关联 · 插入排序输出结果(K1):
a[j + 1] = key是落位语句。
判断题:快速排序 = 分治:选一个基准元素,把小于基准的放左边、大于基准的放右边(分区),再对左右两部分递归排序。
考点:快排的基本思想(E1)。
解析:分治三件套:选基准 → 分区(小的在左、大的在右)→ 对左右子区间递归。✅ 正确
排除法:无(判断题)。混淆点:分区后基准落在最终位置,之后不再参与递归。
关联 · 一次分区后的状态(L1):分区函数的代码实现。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:快速排序平均与最坏情况的时间复杂度分别是?
考点:快排的时间复杂度(E2)。
解析:平均每次分区把问题一分为二 → ;最坏每次分区只排除基准自身(如已有序 + 固定首元素基准)→ 。正确答案 A。
排除法:B 忽略最坏;C 忽略平均;D 说反。
关联 · 快排的最坏情况(H2):最坏情况的触发条件。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:快速排序不稳定——分区时的隔空交换会打乱相等元素的相对顺序。
考点:快排的不稳定性(E3)。
解析:分区时元素隔空交换,相等元素的相对顺序可能被颠倒 → 不稳定。✅ 正确
排除法:无(判断题)。混淆点:稳定性与"分区写法"无关,任何常规分区都可能隔空换位。
关联 · 不稳定排序清单(G5):快排是三大不稳定排序之一。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:快速排序的额外空间主要来自?
考点:快排的空间开销(E4)。
解析:快排是原地分区( 额外空间),额外开销来自递归调用栈:平均 、最坏 。正确答案 A。
排除法:B 是归并的空间;C 无依据;D 忽略递归栈。
关联 · 快排的递归深度(L4):已有序时栈深 。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:归并排序 = 分治:先对半分递归排序,再把两个有序子数组合并成一个有序数组。
考点:归并的基本思想(E5)。
解析:分治:先递归把左右两半各自排好,再把两个有序段合并成一个有序段。✅ 正确
排除法:无(判断题)。混淆点:归并是"先排序后合并"(自顶向下),合并时两半必须已有序。
关联 · 合并两个有序段(M1):merge 的代码实现。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:归并排序的时间复杂度(无论输入如何)是?
考点:归并的时间复杂度(E6)。
解析:每层合并总代价 ,共 层 → ,且与输入无关(无最好最坏之分)。正确答案 A。
排除法:B 是 家族的复杂度;C 是一层合并的代价;D 是层数。
关联 · 归并的层数(H4): 个元素分 层。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:归并排序需要 的辅助数组,并且是稳定排序。
考点:归并的空间与稳定性(E7)。
解析:合并需要 辅助数组(tmp);合并时相等元素先取左边 → 稳定。✅ 正确
排除法:无(判断题)。混淆点:稳定性来自"相等先取左"(M7),空间来自 tmp 数组(M6)。
关联 · 归并的辅助数组(M6):原地合并会覆盖未处理数据。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:堆排序 = 先建堆,再反复把堆顶(最大或最小)与末尾元素交换并向下调整, 次后数组有序。
考点:堆排序的基本思想(F1)。
解析:建堆 → 反复"堆顶与末尾交换 + 向下调整", 次后数组升序(大根堆)或降序(小根堆)。✅ 正确
排除法:无(判断题)。混淆点:建堆后数组不是有序的,只是满足堆序(N7)。
关联 · 建堆后的数组(N7):
{3,8,1,9,2,7}建堆后9 8 7 3 2 1。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:堆排序的时间复杂度与额外空间复杂度分别是?
考点:堆排序的复杂度(F2)。
解析:建堆 + 次"取堆顶 "= ;原地交换,额外空间 。正确答案 A。
排除法:B 复杂度错;C 空间错;D 忽略了取堆顶的对数代价。
关联 · 堆排序的输出(N6):小根堆依次取顶即升序。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:堆排序不稳定——建堆与反复交换堆顶的过程会打乱相等元素的相对顺序。
考点:堆排序的不稳定性(F3)。
解析:建堆的隔层交换与"堆顶↔末尾"的远距离交换都会打乱相等元素顺序 → 不稳定。✅ 正确
排除法:无(判断题)。混淆点:堆排序是唯一" + + 不稳定"的组合,性价比高。
关联 · 不稳定排序清单(G5):堆排序是三大不稳定排序之一。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:计数排序 = 统计每个可能值出现的次数,再按值从小到大依次输出(每个值输出其出现次数遍)。
考点:计数排序的基本思想(F4)。
解析:统计每个可能值出现次数,按值从小到大、每个值输出其次数遍。不比较元素。✅ 正确
排除法:无(判断题)。混淆点:计数数组大小 = 值域(最大值 + 1),不是数据个数。
关联 · 计数排序输出(N1):值域 的输出过程。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:计数排序对 个元素、值域 排序,时间复杂度是?
考点:计数排序的复杂度(F5)。
解析:统计 + 输出 (要扫一遍值域)→ , 为值域大小。正确答案 A。
排除法:B 是比较排序的复杂度;C 无依据;D()无依据。
关联 · 计数排序的适用与稳定(F6): 太大就不划算。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:计数排序适合整数且值域较小的场景,并且可以实现为稳定排序(配合前缀和)。
考点:计数排序的适用与稳定(F6)。
解析:适合整数且值域小(如成绩 );配合前缀和(pos 数组)可以做到稳定。✅ 正确
排除法:无(判断题)。混淆点:值域 时计数数组开不出来,改用其他排序。
关联 · 前缀和定位起始(N3):
pos[v]= 值 v 的起始输出位置。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:C++ 的 sort(a, a + n) 默认升序排列;第三个参数可传自定义比较器(如 greater<int>()、lambda 表达式)实现降序或按关键字排序——这是初赛完善程序的常考点。
考点:sort 函数与自定义比较器(F7)。
解析:sort(a, a + n) 默认升序;第三参数传比较器实现降序或按关键字排序——初赛完善程序多次考"排序 + 贪心/二分"的组合。✅ 正确
排除法:无(判断题)。混淆点:比较器返回 true 表示"第一个参数应排在第二个之前"。
关联 · 补全排队接水(O3):O3 里的
less<int>()就是比较器参数。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:以下哪组排序的最坏时间复杂度都是 ?
考点:三种 O(n²) 排序(G1)。
解析:冒泡、选择、插入的最坏复杂度都是 (比较或移动次数 级别)。正确答案 A。
排除法:B 是 家族;C 是 级别;D 是 家族。
关联 · 冒泡的时间复杂度(B3):三个 各有最好情况差异。
单选题:平均时间复杂度为 的排序是?
考点:平均 O(n log n) 家族(G2)。
解析:快排(平均)、归并、堆排序平均都是 。正确答案 A。
排除法:B 是 家族;C 中插入是 、计数是 ;D 插入排序是 ,不属于本家族。
关联 · 最坏 O(n log n) 的排序(G3):平均与最坏要分开看。
单选题:最坏情况下时间复杂度也保持 的排序是?
考点:最坏 O(n log n) 的排序(G3)。
解析:归并(固定分层)、堆排序(固定 次取顶)最坏也是 ;快排最坏会退化 。正确答案 A。
排除法:B 中快排/冒泡最坏 ;C 全是 ;D 是 。
关联 · 快排的时间复杂度(E2):快排"平均优秀、最坏翻车"。
单选题:以下哪组排序全部是稳定的?
考点:稳定排序清单(G4)。
解析:稳定清单:冒泡、插入、归并、计数。正确答案 A。
排除法:B 全是三大不稳定;C 混入选择/快排;D 混入堆排序。
关联 · 不稳定排序清单(G5):与本题互为镜像,背成一组。
判断题:选择排序、快速排序、堆排序都是不稳定排序。
考点:不稳定排序清单(G5)。
解析:选择(隔空交换)、快排(分区交换)、堆排序(堆顶交换)——三大不稳定。✅ 正确
排除法:无(判断题)。混淆点:计数排序可以做成稳定(前缀和版),别把它算进不稳定。
关联 · 稳定排序清单(G4):稳定清单 = 冒泡/插入/归并/计数。
判断题:基于元素比较的排序,最坏时间复杂度至少是 ;计数/基数等非比较排序可以做到 级别,因此能"突破"这个下界。
考点:比较排序的下界(G6)。
解析:比较排序最坏至少 (决策树论证);计数排序不做比较,可做到 级别。✅ 正确
排除法:无(判断题)。混淆点:"突破下界"靠的是放弃比较,不是更聪明的比较。
关联 · 比较排序与非比较排序(A4):两大类别的根本分野。
单选题: 个随机整数要排序,最稳妥的选择是?
考点:排序算法的选择(G7)。
解析: 时 约 步、 约 步——必须选快排/归并(或 sort)。正确答案 A。
排除法:B/C/D 都是 , 规模直接超时。
关联 · 插入的适用场景(D4):小数据/基本有序才轮得到 。
单选题:判断稳定性的直观依据:排序中是否会发生隔空交换(两个不相邻元素直接互换)或相等元素被越过。以下哪个是稳定排序?
考点:稳定性的判断依据(H1)。
解析:隔空交换(不相邻元素直接互换)或"相等元素被越过"都会破坏稳定;插入只做相邻后移、相等时不越过 → 稳定。正确答案 A。
排除法:B(选择)隔空交换;C(快排)分区交换;D(堆)堆顶交换——全是隔空换位。
关联 · 选择的不稳定性(C3):
{2,2,1}的隔空交换实例。
单选题:快速排序退化为 的典型情况是?
考点:快排的最坏情况(H2)。
解析:已有序 + 固定首元素基准 → 每次分区基准落到端点,只排除 1 个元素 → 递归 层、。正确答案 A。
排除法:B(随机)恰恰是防退化的手段;C(取中位数)也是好基准;D(三分区)处理全相等很快。
关联 · 随机基准防退化(L6):随机/三数取中打破最坏输入。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:待排序数据是取值范围高达 的整数(如坐标、编号),还能用计数排序吗?
考点:计数排序的值域限制(H3)。
解析:计数数组大小 = 值域(最大值 + 1);值域高达 时数组开不下,计数排序不可用。正确答案 A。
排除法:B/C 错——不是"稍慢"或"是整数就行",是数组根本开不出;D 荒谬( 规模下应改用 的比较排序)。
关联 · 计数排序的复杂度(F5): 里 太大就不划算。
单选题:归并排序对 个元素排序,分治分裂的层数是?
考点:归并的层数(H4)。
解析:,分裂 层(每层合并总代价 ,所以总 )。正确答案 A。
排除法:B 把层数当元素数;C 多算一层;D 少算一层。
关联 · 归并的时间复杂度(E6):层数 × 每层代价 = 复杂度。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:以下结论全部正确——"冒泡、插入稳定;选择、快排、堆不稳定;归并最坏 且稳定;快排平均 但最坏 "。
考点:排序结论综合判断(H5)。
解析:四句全部正确:稳定 = 冒泡/插入/归并/计数;不稳定 = 选择/快排/堆;归并最坏 且稳定;快排平均 、最坏 。✅ 正确
排除法:无(判断题)。混淆点:这套"复杂度 × 稳定性"总表是 CSP-J 每年必考点,逐条背熟。
关联 · 复杂度与稳定性总表(G1~G6):本组前六题已逐条展开。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 3, 8, 1, 7}; 05 int n = 5; 06 for (int i = 0; i < n - 1; i++) // n-1 趟 07 for (int j = 0; j < n - 1 - i; j++) // 每趟比较相邻元素 08 if (a[j] > a[j + 1]) swap(a[j], a[j + 1]); 09 for (int i = 0; i < n; i++) cout << a[i] << " "; 10 return 0; 11}
单选题:程序输出是?
考点:冒泡排序输出结果(I1)。
解析:双层循环 趟、每趟相邻比较逆序交换,最终升序 1 3 5 7 8。正确答案 A。
实现要点:冒泡框架 = 外层趟数 i < n-1 + 内层 j < n-1-i(每趟少比较一个已就位的)。手算技巧:一轮一轮写数组状态,末尾元素逐轮固定。
排除法:B 是降序结果;C 是原数组;D 顺序错乱。
关联 · 冒泡的基本思想(B1):框架就是思想的直译。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 3, 8, 1, 7}; 05 int n = 5, cnt = 0; 06 for (int i = 0; i < n - 1; i++) 07 for (int j = 0; j < n - 1 - i; j++) 08 if (a[j] > a[j + 1]) { swap(a[j], a[j + 1]); cnt++; } // 每次交换计数 09 cout << cnt; 10 return 0; 11}
单选题:程序输出是?
考点:冒泡的交换次数(I2)。
解析:逐轮数:第 1 轮换 3 次(5↔3、8↔1、8↔7)、第 2 轮 1 次(5↔1)、第 3 轮 1 次(3↔1)、第 4 轮 0 次 → 共 5 次。正确答案 A。
实现要点:交换计数题 = 在 swap 处 cnt++。手算画每轮状态:{5,3,8,1,7} → 3 5 1 7 8 → 3 1 5 7 8 → 1 3 5 7 8 → 不变。
排除法:B(4)漏数第 3 轮;C(6)多数;D(8)是趟数×2 的误解。
关联 · 冒泡的趟数(B6):交换次数与趟数不是一回事。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {9, 2, 7, 4, 1}; 05 int n = 5; 06 for (int j = 0; j < n - 1; j++) // 只做第一趟 07 if (a[j] > a[j + 1]) swap(a[j], a[j + 1]); 08 for (int i = 0; i < n; i++) cout << a[i] << " "; 09 return 0; 10}
单选题:程序输出是?
考点:冒泡一趟后的状态(I3)。
解析:{9,2,7,4,1} 第一趟:9↔2、9↔7、9↔4、9↔1 → 2 7 4 1 9,最大值 9 冒到末尾。正确答案 A。
实现要点:单趟 = 只跑内层循环一次。手算:想象大元素像气泡连续向右移动,一路换到底。
排除法:B 是完整排序结果;C 漏了 9 与 4 的交换;D 是降序方向。
关联 · 冒泡第一轮的结果(B2):同款题的概念版。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {1, 2, 3, 5, 4}; // 基本有序 05 int n = 5, pass = 0; 06 bool swapped = true; // 本轮是否有交换 07 for (int i = 0; i < n - 1 && swapped; i++) { 08 swapped = false; 09 for (int j = 0; j < n - 1 - i; j++) 10 if (a[j] > a[j + 1]) { swap(a[j], a[j + 1]); swapped = true; } 11 pass++; // 每跑一趟计数 12 } 13 cout << pass; 14 return 0; 15}
单选题:程序输出是?
考点:冒泡优化的趟数(I4)。
解析:{1,2,3,5,4}:第 1 趟交换 5↔4 后排好;第 2 趟无交换、swapped 变假 → 退出。共 2 趟。正确答案 A。
实现要点:优化 = swapped 标志 + 外层条件 i < n-1 && swapped。手算看"最后一次交换发生在第几趟",该趟后还需一趟确认无交换。
排除法:B(4)是无优化版的趟数;C(1)只算到交换那趟;D 无依据。
关联 · 冒泡的提前结束优化(B5):提前退出的来源。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {3, 1, 4, 1, 5}; 05 int n = 5; 06 for (int i = 0; i < n - 1; i++) 07 for (int j = 0; j < n - 1 - i; j++) 08 if (a[j] < a[j + 1]) swap(a[j], a[j + 1]); // 注意:比较方向是 < 09 for (int i = 0; i < n; i++) cout << a[i] << " "; 10 return 0; 11}
单选题:程序输出是?
考点:降序冒泡(I5)。
解析:比较条件改成 a[j] < a[j+1](逆序=左小右大)→ 每轮把最小"冒"到末尾 → 降序 5 4 3 1 1。正确答案 A。
实现要点:升序改降序只动一个符号:> 改 <。手算验证边界:两个 1 相等不交换(稳定)。
排除法:B 是升序结果;C 是原数组;D 只有部分排好。
关联 · 升序与降序(A2):方向由比较符决定。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {4, 2, 5, 1, 3}; 05 int n = 5; 06 for (int i = 0; i < 2; i++) // 只做前 2 趟 07 for (int j = 0; j < n - 1 - i; j++) 08 if (a[j] > a[j + 1]) swap(a[j], a[j + 1]); 09 for (int i = 0; i < n; i++) cout << a[i] << " "; 10 return 0; 11}
单选题:程序输出是?
考点:冒泡两趟后的状态(I6)。
解析:{4,2,5,1,3} 第 1 趟 → 2 4 1 3 5;第 2 趟(比较 3 次)→ 2 1 3 4 5。末尾 5、4 已就位。正确答案 A。
实现要点:第 k 趟后末尾 k 个元素就位。手算逐趟写状态,注意内层范围每趟减 1。
排除法:B 是三趟后的结果;C 是第 1 趟后的状态;D 交换次序错。
关联 · 冒泡一趟后的状态(I3):单趟与多趟的递进。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 3, 8, 1, 7}; 05 int n = 5; 06 for (int i = 0; i < n - 1; i++) { 07 int p = i; // 假定 a[i] 是当前最小 08 for (int j = i + 1; j < n; j++) 09 if (a[j] < a[p]) p = j; // 找 [i, n-1] 中最小的下标 10 swap(a[i], a[p]); // 最小元素放到前面 11 } 12 for (int i = 0; i < n; i++) cout << a[i] << " "; 13 return 0; 14}
单选题:程序输出是?
考点:选择排序输出结果(J1)。
解析:每轮选最小放最前:1→最前、3→第二位、5→第三位、7→第四位 → 1 3 5 7 8。正确答案 A。
实现要点:选择框架 = 外层 i 定位置 + 内层打擂台找 [i, n-1] 最小值下标 p + swap(a[i], a[p])。手算:每轮圈出最小元素与其落点。
排除法:B 是降序;C 只排了前两个;D 是原数组。
关联 · 选择的基本思想(C1):框架 = 思想的直译。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 3, 8, 1, 7}; 05 int n = 5, cnt = 0; 06 for (int i = 0; i < n - 1; i++) { 07 int p = i; 08 for (int j = i + 1; j < n; j++) 09 if (a[j] < a[p]) p = j; 10 if (p != i) { swap(a[i], a[p]); cnt++; } // 位置变了才交换 11 } 12 cout << cnt; 13 return 0; 14}
单选题:程序输出是?
考点:选择的交换次数(J2)。
解析:第 1 轮换(5↔1)、第 2 轮 p==i 不换、第 3 轮换(8↔5)、第 4 轮换(8↔7)→ 共 3 次。正确答案 A。
实现要点:if (p != i) 才交换——最小元素恰好已在原位时不换。手算逐轮列出 p 与交换动作。
排除法:B(4)把 p==i 那轮也算上;C(5)是冒泡的交换次数(I2);D 漏一轮。
关联 · 选择的比较与交换次数(C2):交换至多 次。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {9, 2, 7, 4, 1}; 05 int n = 5; 06 int i = 0, p = 0; // 只做第一轮 07 for (int j = 1; j < n; j++) 08 if (a[j] < a[p]) p = j; 09 swap(a[i], a[p]); 10 for (int i = 0; i < n; i++) cout << a[i] << " "; 11 return 0; 12}
单选题:程序输出是?
考点:选择一轮后的状态(J3)。
解析:{9,2,7,4,1} 第一轮打擂台得最小 1(下标 4),与 a[0] 交换 → 1 2 7 4 9。正确答案 A。
实现要点:单轮 = 找 p + 一次交换。手算:圈出最小元素,直接与首元素对调,其余不动。
排除法:B 是完整排序;C 交换对象错;D 是降序结果。
关联 · 选择第 i 轮就位(C5):第 1 轮后 a[0] 已就位。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 3, 8, 1, 7}; 05 int n = 5; 06 for (int i = n - 1; i > 0; i--) { 07 int p = 0; // 找 [0, i] 中最大的下标 08 for (int j = 1; j <= i; j++) 09 if (a[j] > a[p]) p = j; 10 swap(a[i], a[p]); // 最大元素放到末尾 11 } 12 for (int i = 0; i < n; i++) cout << a[i] << " "; 13 return 0; 14}
单选题:程序输出是?
考点:选最大放末尾(J4)。
解析:i 从 4 递减:第 1 轮最大 8 换到末位 → 5 3 7 1 8;第 2 轮 7 就位 → 5 3 1 7 8;第 3 轮 5 就位 → 1 3 5 7 8 → 升序完成。正确答案 A。
实现要点:对称写法 = i 从 n-1 递减、找 [0, i] 最大值、swap(a[i], a[p])。手算从数组末尾往前固定元素。
排除法:B 是降序;C 是第一轮后的中间状态;D 次序错。
关联 · 选最大放末尾(C6):两种方向等价。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[4] = {3, 1, 4, 2}; 05 int n = 4, cnt = 0; 06 for (int i = 0; i < n - 1; i++) { 07 int p = i; 08 for (int j = i + 1; j < n; j++) { 09 if (a[j] < a[p]) p = j; 10 cnt++; // 每比较一次计数 11 } 12 } 13 cout << cnt; 14 return 0; 15}
单选题:程序输出是?
考点:选择的比较次数(J5)。
解析:比较次数 (与数据内容无关)。正确答案 A。
实现要点:选择排序比较次数固定 。手算:内层循环圈数递减,逐轮相加。
排除法:B(12)是 的误解;C(4)只算最后一轮;D 无依据。
关联 · 选择的比较与交换次数(C2):比较 、交换 。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 1, 4, 2, 3}; 05 int n = 5; 06 for (int i = 0; i < n - 1; i++) { 07 int p = i; 08 for (int j = i + 1; j < n; j++) 09 if (a[j] < a[p]) p = j; 10 swap(a[i], a[p]); 11 cout << a[i] << " "; // 每轮输出刚就位的元素 12 } 13 return 0; 14}
单选题:程序输出是?
考点:每轮就位的元素(J6)。
解析:第 1~4 轮分别把 1、2、3、4 放到最前,每轮输出 a[i] → 1 2 3 4。正确答案 A。
实现要点:第 轮结束后 a[i] 就是全局第 小元素(已就位)。手算:每轮圈出未排部分的最小值。
排除法:B 是降序方向;C 多输出第 5 个元素(外层只到 n-2);D 次序错。
关联 · 选择第 i 轮就位(C5):就位性质的代码实证。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 3, 8, 1, 7}; 05 int n = 5; 06 for (int i = 1; i < n; i++) { 07 int key = a[i], j = i - 1; // 待插入元素 key 08 while (j >= 0 && a[j] > key) { // 比 key 大的逐个后移 09 a[j + 1] = a[j]; 10 j--; 11 } 12 a[j + 1] = key; // key 落位 13 } 14 for (int i = 0; i < n; i++) cout << a[i] << " "; 15 return 0; 16}
单选题:程序输出是?
考点:插入排序输出结果(K1)。
解析:逐个插入:3→3 5、8 不动、1 插到最前、7 插到 5 与 8 之间 → 1 3 5 7 8。正确答案 A。
实现要点:插入框架 = key = a[i] 暂存 + while 把比 key 大的后移 + a[j+1] = key 落位。手算:像理牌,每张新牌从右往左找到位置。
排除法:B 是降序;C 只插了第一个;D 次序错。
关联 · 插入的基本思想(D1):抓牌类比。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {9, 2, 7, 4, 1}; 05 int n = 5; 06 for (int i = 1; i <= 2; i++) { // 只插入前 2 个元素 07 int key = a[i], j = i - 1; 08 while (j >= 0 && a[j] > key) { a[j + 1] = a[j]; j--; } 09 a[j + 1] = key; 10 } 11 for (int i = 0; i < n; i++) cout << a[i] << " "; 12 return 0; 13}
单选题:程序输出是?
考点:插入两轮后的状态(K2)。
解析:插 2 → 2 9 7 4 1;插 7(9 后移)→ 2 7 9 4 1。前 3 个元素有序。正确答案 A。
实现要点:第 轮后前缀 a[0..i] 有序。手算:只看前缀,新元素落位后其余不动。
排除法:B 把后面的元素也算进来排了;C 没把 9 后移;D 是完整结果。
关联 · 插入的前缀有序(D5):前缀有序 ≠ 最终就位。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[4] = {4, 3, 2, 1}; // 完全逆序 05 int n = 4, cnt = 0; 06 for (int i = 1; i < n; i++) { 07 int key = a[i], j = i - 1; 08 while (j >= 0 && a[j] > key) { 09 a[j + 1] = a[j]; // 每移动一次计数 10 j--; 11 cnt++; 12 } 13 a[j + 1] = key; 14 } 15 cout << cnt; 16 return 0; 17}
单选题:程序输出是?
考点:逆序输入的移动次数(K3)。
解析:{4,3,2,1} 移动 次(第 1 个插 1 次、第 2 个插 2 次、第 3 个插 3 次)。正确答案 A。
实现要点:逆序是最坏输入,移动次数 。手算:每轮 while 执行次数 = 新元素前面比它大的个数。
排除法:B(4)只算了 ;C(12)是 的误解;D 无依据。
关联 · 已有序的移动次数(K5):最好 0 次、最坏 次。
单选题:插入排序内层循环 while (j >= 0 && a[j] > key) 中,条件 a[j] > key 的作用是?
考点:内层 while 条件的作用(K4)。
解析:a[j] > key 逐个把比 key 大的元素右移一位,循环停止处就是 key 的插入位置。正确答案 A。
排除法:B 与越界无关(越界靠 j >= 0 防);C 不检测重复;D 与速度无关。
关联 · 插入的移动实现(D6):移动 + 落位两步走。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {1, 2, 3, 4, 5}; // 已经有序 05 int n = 5, cnt = 0; 06 for (int i = 1; i < n; i++) { 07 int key = a[i], j = i - 1; 08 while (j >= 0 && a[j] > key) { 09 a[j + 1] = a[j]; 10 j--; 11 cnt++; 12 } 13 a[j + 1] = key; 14 } 15 cout << cnt; 16 return 0; 17}
单选题:程序输出是?
考点:已有序的移动次数(K5)。
解析:数组已有序,内层 a[j] > key 一次都不成立 → 移动 0 次,输出 0。正确答案 A。
实现要点:最好情况 = 有序输入 → (只比较不移动)。对比 K3:同样 4 个元素逆序移动 6 次。
排除法:B(4)是插入次数;C(10)是全部比较次数;D 无依据。
关联 · 插入的时间复杂度(D2):最好 的来源。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[6] = {3, 1, 4, 1, 5, 9}; 05 int n = 6; 06 for (int i = 1; i <= 2; i++) { // 前 3 个元素(a[0..2])排好序 07 int key = a[i], j = i - 1; 08 while (j >= 0 && a[j] > key) { a[j + 1] = a[j]; j--; } 09 a[j + 1] = key; 10 } 11 for (int i = 0; i < n; i++) cout << a[i] << " "; 12 return 0; 13}
单选题:程序输出是?
考点:插入排序前缀状态(K6)。
解析:插 1 → 1 3 4 1 5 9;插 4(前面 3 < 4 不移动)→ 不变。前 3 个 1 3 4 有序,后面未动。正确答案 A。
实现要点:注意数组里有两个 1——第一个 1 是"后来插到前面"的,说明前缀只是暂时有序(D5)。手算时先写 key、再数 while 移动次数。
排除法:B 是完整排序结果;C 是原数组;D 交换次序错。
关联 · 插入两轮后的状态(K2):同款题的 6 元素版。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[7] = {6, 1, 2, 7, 9, 3, 5}; 05 int n = 7, pivot = a[0]; // 以 a[0] = 6 为基准 06 int i = 0; // i 指向最后一个小于基准的位置 07 for (int j = 1; j < n; j++) 08 if (a[j] < pivot) { i++; swap(a[i], a[j]); } 09 swap(a[0], a[i]); // 基准落位 10 for (int k = 0; k < n; k++) cout << a[k] << " "; 11 return 0; 12}
单选题:程序输出是?
考点:一次分区后的状态(L1)。
解析:基准 6:小于 6 的 1、2、3、5 依次换到前面,最后 6 与 a[4] 交换落位 → 5 1 2 3 6 7 9。正确答案 A。
实现要点:分区 = i 记录"最后一个小于基准的位置",遇到小于基准的 i++ 交换;最后 swap(a[0], a[i]) 让基准落位。手算:小于基准的按顺序挤到左边,基准放中间。
排除法:B 是完整排序结果;C 没做最后的基准落位交换;D 落位位置错。
关联 · 快排的基本思想(E1):分区是快排的核心。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[6]; 04void qs(int l, int r) { // 对 [l, r] 快速排序 05 if (l >= r) return; 06 int pivot = a[l], i = l; 07 for (int j = l + 1; j <= r; j++) 08 if (a[j] < pivot) { i++; swap(a[i], a[j]); } 09 swap(a[l], a[i]); 10 qs(l, i - 1); 11 qs(i + 1, r); 12} 13int main() { 14 int b[6] = {4, 2, 6, 1, 3, 5}; 15 for (int i = 0; i < 6; i++) a[i] = b[i]; 16 qs(0, 5); 17 for (int i = 0; i < 6; i++) cout << a[i] << " "; 18 return 0; 19}
单选题:程序输出是?
考点:快排递归输出(L2)。
解析:分区 + 左右递归,完整排序 → 1 2 3 4 5 6。正确答案 A。
实现要点:快排递归框架 = if (l >= r) return + 分区 + qs(l, i-1) + qs(i+1, r)。手算:先分区看基准落位,再分别处理两段。
排除法:B 是降序;C 是原数组;D 右边没排好。
关联 · 快排缺递归边界(P4):没有
l >= r的终止会栈溢出。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[6] = {3, 1, 4, 1, 5, 2}; 05 int n = 6, pivot = a[0], i = 0; 06 for (int j = 1; j < n; j++) 07 if (a[j] < pivot) { i++; swap(a[i], a[j]); } 08 swap(a[0], a[i]); 09 cout << i; // 基准最终落在的下标 10 return 0; 11}
单选题:程序输出是?
考点:基准落位下标(L3)。
解析:基准 3,小于 3 的有 1、1、2 三个 → 基准最终落在下标 3。正确答案 A。
实现要点:分区后基准落位下标 = "小于基准的元素个数"(基准从 a[0] 出发时)。手算:数出比基准小的个数即可,无需模拟交换。
排除法:B 漏数一个 1;C 多算;D 是基准起点。
关联 · 一次分区后的状态(L1):落位下标的快捷算法。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[5], mx = 0, dep = 0; 04void qs(int l, int r) { 05 if (l >= r) return; 06 dep++; 07 mx = max(mx, dep); // 记录最大递归深度 08 int pivot = a[l], i = l; 09 for (int j = l + 1; j <= r; j++) 10 if (a[j] < pivot) { i++; swap(a[i], a[j]); } 11 swap(a[l], a[i]); 12 qs(l, i - 1); 13 qs(i + 1, r); 14 dep--; 15} 16int main() { 17 int b[5] = {1, 2, 3, 4, 5}; // 已有序,固定首元素作基准 18 for (int i = 0; i < 5; i++) a[i] = b[i]; 19 qs(0, 4); 20 cout << mx; 21 return 0; 22}
单选题:程序输出是?
考点:快排的递归深度(L4)。
解析:已有序 {1,2,3,4,5} + 首元素基准:每层只排除基准自身,递归链 qs(0,4) → qs(1,4) → qs(2,4) → qs(3,4)(qs(4,4) 因 l >= r 直接返回不计数)→ 最大深度 4。正确答案 A。
实现要点:最坏递归深度 = (叶子调用不进入函数体)。手算:画递归链,注意 l >= r 的调用不增加深度。
排除法:B(5)把叶子调用也计入;C、D 是随机输入的量级。
关联 · 快排的空间开销(E4):栈深最坏 。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:快排每次固定选首元素作基准、且数组已有序时,每次分区只排除基准自身,退化为 。
考点:快排最坏情况识别(L5)。
解析:已有序 + 固定首元素基准 → 每次分区极不平衡(一边空、一边 个)→ 。✅ 正确
排除法:无(判断题)。混淆点:反过来"固定首元素 + 随机数组"平均仍 。
关联 · 快排的最坏情况(H2):触发条件与对策。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:为避免快排退化成 ,常用的改进是?
考点:随机基准防退化(L6)。
解析:随机选基准(或三数取中)使最坏输入几乎不会出现,期望 。正确答案 A。
排除法:B/C 是退化的根源;D 用 算法替代是倒退。
关联 · 快排的时间复杂度(E2):平均优秀的保证。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[5] = {2, 5, 1, 4, 3}; 04void qs(int l, int r) { 05 if (l >= r) return; 06 int pivot = a[l], i = l; 07 for (int j = l + 1; j <= r; j++) 08 if (a[j] < pivot) { i++; swap(a[i], a[j]); } 09 swap(a[l], a[i]); 10 cout << i << " "; // 输出本轮基准落位下标 11 qs(l, i - 1); 12 qs(i + 1, r); 13} 14int main() { qs(0, 4); return 0; }
单选题:程序输出是?
考点:每轮基准下标序列(L7)。
解析:qs(0,4) 基准 2 落位 1 → 输出 1;qs(2,4) 基准 5 落位 4 → 输出 4;qs(2,3) 基准 3 落位 2 → 输出 2。序列 1 4 2。正确答案 A。
实现要点:递归顺序 = 先序(先分区输出、再左右递归)。手算:按"基准值排序后位置"推落位,按递归展开顺序排输出。
排除法:B 把右子树输出提前;C 是首轮落位搞反;D 无依据。
关联 · 快排递归输出(L2):输出时机决定序列形态。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[8] = {2, 4, 7, 9, 1, 3, 5, 8}; // 左半 [0,3] 与右半 [4,7] 各自有序 05 int tmp[8]; 06 int l = 0, mid = 3, r = 7; 07 int i = l, j = mid + 1, k = l; 08 while (i <= mid && j <= r) { // 合并两个有序段 09 if (a[i] <= a[j]) tmp[k++] = a[i++]; 10 else tmp[k++] = a[j++]; 11 } 12 while (i <= mid) tmp[k++] = a[i++]; 13 while (j <= r) tmp[k++] = a[j++]; 14 for (int t = l; t <= r; t++) { a[t] = tmp[t]; cout << a[t] << " "; } 15 return 0; 16}
单选题:程序输出是?
考点:合并两个有序段(M1)。
解析:双指针 i、j 分别扫两段,谁小取谁 → 1 2 3 4 5 7 8 9。正确答案 A。
实现要点:merge 框架 = 双指针比较 + 两个"收尾"while(把剩余段倒进 tmp)+ 回写。手算:左右各放一根手指,反复取较小者。
排除法:B 是原数组;C 是降序;D 是两段原样拼接。
关联 · 归并的基本思想(E5):合并是归并的核心。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[6], tmp[6]; 04void ms(int l, int r) { // 对 [l, r] 归并排序 05 if (l >= r) return; 06 int mid = (l + r) / 2; 07 ms(l, mid); 08 ms(mid + 1, r); 09 int i = l, j = mid + 1, k = l; 10 while (i <= mid && j <= r) { 11 if (a[i] <= a[j]) tmp[k++] = a[i++]; 12 else tmp[k++] = a[j++]; 13 } 14 while (i <= mid) tmp[k++] = a[i++]; 15 while (j <= r) tmp[k++] = a[j++]; 16 for (int t = l; t <= r; t++) a[t] = tmp[t]; 17} 18int main() { 19 int b[6] = {6, 5, 3, 1, 8, 7}; 20 for (int i = 0; i < 6; i++) a[i] = b[i]; 21 ms(0, 5); 22 for (int i = 0; i < 6; i++) cout << a[i] << " "; 23 return 0; 24}
单选题:程序输出是?
考点:归并排序输出(M2)。
解析:递归分治 + 合并,完整排序 → 1 3 5 6 7 8。正确答案 A。
实现要点:归并框架 = ms(l, mid) + ms(mid+1, r) + merge + 回写。手算:自底向上看——先相邻两两合并,再四四合并。
排除法:B 是降序;C 是原数组;D 合并不完整。
关联 · 合并两个有序段(M1):框架与 M1 的合并函数衔接。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[8], tmp[8]; 04void ms(int l, int r) { 05 if (l >= r) return; 06 int mid = (l + r) / 2; 07 ms(l, mid); 08 ms(mid + 1, r); 09 int i = l, j = mid + 1, k = l; 10 while (i <= mid && j <= r) { 11 if (a[i] <= a[j]) tmp[k++] = a[i++]; 12 else tmp[k++] = a[j++]; 13 } 14 while (i <= mid) tmp[k++] = a[i++]; 15 while (j <= r) tmp[k++] = a[j++]; 16 for (int t = l; t <= r; t++) a[t] = tmp[t]; 17 if (r - l + 1 == 4) { // 输出所有长度为 4 的合并结果 18 for (int t = l; t <= r; t++) cout << a[t] << " "; 19 } 20} 21int main() { 22 int b[8] = {3, 6, 2, 5, 8, 1, 7, 4}; 23 for (int i = 0; i < 8; i++) a[i] = b[i]; 24 ms(0, 7); 25 return 0; 26}
单选题:程序输出是?
考点:归并长度为 4 的段(M3)。
解析:自底向上:3,6 2,5 → 2 3 5 6;8,1 7,4 → 1 4 7 8。两个长度为 4 的合并结果依次输出 → 2 3 5 6 1 4 7 8。正确答案 A。
实现要点:长度 4 的段 = 先合并出两个长度为 2 的段、再合并它们。手算自底向上分层,输出时机在"回写之后"。
排除法:B 是原数组;C 是最终结果;D 每段内部次序错。
关联 · 归并的层数(H4):本题展示的是第 2 层(长度 4)。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[4] = {3, 1, 4, 2}; 04int tmp[4]; 05long long cnt = 0; 06void ms(int l, int r) { 07 if (l >= r) return; 08 int mid = (l + r) / 2; 09 ms(l, mid); 10 ms(mid + 1, r); 11 int i = l, j = mid + 1, k = l; 12 while (i <= mid && j <= r) { 13 if (a[i] <= a[j]) tmp[k++] = a[i++]; 14 else { 15 tmp[k++] = a[j++]; 16 cnt += mid - i + 1; // 核心:a[j] 小于左段剩余全部元素 17 } 18 } 19 while (i <= mid) tmp[k++] = a[i++]; 20 while (j <= r) tmp[k++] = a[j++]; 21 for (int t = l; t <= r; t++) a[t] = tmp[t]; 22} 23int main() { ms(0, 3); cout << cnt; return 0; }
单选题:程序输出是?
考点:归并统计逆序对(M4)。
解析:{3,1,4,2} 逆序对:(3,1)、(3,2)、(4,2) 共 3 对。归并时"右段元素小于左段剩余全部"处累计。正确答案 A。
实现要点:逆序对模板 = 归并 merge 中 a[j] < a[i] 时 cnt += mid - i + 1(右段该元素与左段剩余每个元素都构成逆序对)。手算可先用暴力 核对小样例。
排除法:B 漏数 (4,2);C 多算;D 是 的误解。
关联 · 归并的比较次数(M5):逆序对统计的复杂度与归并排序相同。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:归并排序合并两个有序段时,比较次数最多约为两段长度之和(每比较一次至少确定一个元素的位置)。
考点:归并的比较次数(M5)。
解析:合并两段时每次比较至少确定一个元素位置,总比较次数 ≤ 两段长度之和(约 级别)。✅ 正确
排除法:无(判断题)。混淆点:某一侧耗尽后,剩余元素直接搬运、不再比较。
关联 · 归并的时间复杂度(E6):每层合并 由此而来。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
判断题:归并排序合并时必须借助 辅助数组(如 tmp);在原数组上"原地"合并会覆盖尚未处理的数据。
考点:归并的辅助数组(M6)。
解析:merge 必须写到 tmp 再回写 a;直接在 a 上合并会覆盖尚未处理的数据。✅ 正确
排除法:无(判断题)。混淆点:tmp 可以全局开一个 复用,不必每层新开。
关联 · 归并的空间与稳定性(E7): 辅助空间是归并的代价。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:归并排序合并时,把条件 a[i] <= a[j] 改成 a[i] < a[j] 会?
考点:归并的稳定性细节(M7)。
解析:<= 时相等先取左段 → 稳定;改成 < 后相等走 else 分支先取右段 → 相等元素相对顺序颠倒 → 不稳定。正确答案 A。
排除法:B/C 与比较符号无关;D 错——一个符号就改变稳定性。
关联 · 插入的稳定性(D3):同款"等号归属"细节。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[7] = {4, 2, 2, 8, 3, 3, 1}; 05 int cnt[9] = {0}; // 值域 0~8,cnt[v] = v 出现次数 06 for (int i = 0; i < 7; i++) cnt[a[i]]++; 07 for (int v = 0; v <= 8; v++) 08 for (int t = 0; t < cnt[v]; t++) 09 cout << v << " "; // 按值从小到大输出 10 return 0; 11}
单选题:程序输出是?
考点:计数排序输出(N1)。
解析:统计:1×1、2×2、3×2、4×1、8×1;按值 0→8 输出 → 1 2 2 3 3 4 8。正确答案 A。
实现要点:计数排序 = cnt[a[i]]++ 统计 + 双重循环按值输出。手算:先画"值 → 次数"表,再按值从小到大展开。
排除法:B 是降序;C 是原数组;D 输出顺序错。
关联 · 计数排序的基本思想(F4):统计 + 展开两步走。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[6] = {3, 1, 3, 4, 2, 3}; 05 int cnt[6] = {0}; // 值域 0~5 06 for (int i = 0; i < 6; i++) cnt[a[i]]++; 07 for (int v = 0; v <= 5; v++) cout << cnt[v] << " "; // 输出各值的出现次数 08 return 0; 09}
单选题:程序输出是?
考点:计数数组统计(N2)。
解析:{3,1,3,4,2,3} 中值 0~5 出现次数:0 次、1 次、1 次、3 次、1 次、0 次 → 0 1 1 3 1 0。正确答案 A。
实现要点:cnt[v] = 值 v 的出现次数;输出 cnt 数组本身而非排序结果。手算:逐个元素在"值 → 次数"表上画正字。
排除法:B 是原数组;C 漏掉 0 次的值;D 是"值列表"的误解。
关联 · 前缀和定位起始(N3):cnt 是前缀和的原料。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {2, 1, 2, 3, 1}; // 值域 1~3 05 int cnt[5] = {0}, pos[5] = {0}; 06 for (int i = 0; i < 5; i++) cnt[a[i]]++; 07 for (int v = 1; v <= 3; v++) pos[v] = pos[v - 1] + cnt[v - 1]; 08 // 说明:pos[v] = 稳定版计数排序中,值 v 在输出数组里的起始位置 09 for (int v = 1; v <= 3; v++) cout << pos[v] << " "; 10 return 0; 11}
单选题:程序输出是?
考点:前缀和定位起始(N3)。
解析:cnt[1]=2、cnt[2]=2、cnt[3]=1;pos[1]=0、pos[2]=0+2=2、pos[3]=2+2=4 → 0 2 4。正确答案 A。
实现要点:稳定计数排序 = cnt 统计 → pos 前缀和(每个值的起始位置)→ 倒序遍历原数组按 pos 放元素。pos[v] = 值 v 的第一个输出位置。
排除法:B 是 cnt 本身;C 是值列表;D 少算了前缀和。
关联 · 计数排序的适用与稳定(F6):前缀和是稳定性的关键。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {2, 1, 2, 3, 1}; // 值域 1~3 05 int n = 5, cnt[5] = {0}, pos[5] = {0}, out[5]; 06 for (int i = 0; i < n; i++) cnt[a[i]]++; 07 for (int v = 1; v <= 3; v++) pos[v] = pos[v - 1] + cnt[v - 1]; // 前缀和:每个值的起始位置 08 for (int i = 0; i < n; i++) out[pos[a[i]]++] = a[i]; // 按起始位置摆放 09 for (int i = 0; i < n; i++) cout << out[i] << " "; 10 return 0; 11}
单选题:程序输出是?
考点:计数排序稳定版输出(N4)。
解析:cnt = {2,2,1}、pos[1]=0、pos[2]=2、pos[3]=4;正序摆放 → 1 1 2 2 3(两个 2 保持原先后顺序落在下标 2、3——稳定)。正确答案 A。
实现要点:稳定计数排序三步:cnt 统计 → pos 前缀和(每个值的起始位置)→ 遍历原数组 out[pos[a[i]]++] = a[i]。手算:先写 pos 表,再逐个元素"放进它的槽位、槽位后移一格"。
排除法:B 反序摆放;C 槽位错位;D 是降序。
关联 · 前缀和定位起始(N3):pos 数组就是本题的核心。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03struct P { int a, b; }; // 双关键字记录 04int main() { 05 P p[4] = {{2,1},{1,2},{2,2},{1,1}}; 06 sort(p, p + 4, [](P x, P y){ 07 if (x.a != y.a) return x.a < y.a; // 先按第一关键字升序 08 return x.b < y.b; // 再按第二关键字升序 09 }); 10 for (int i = 0; i < 4; i++) cout << p[i].a << "," << p[i].b << " "; 11 return 0; 12}
单选题:程序输出是?
考点:双关键字排序输出(N5)。
解析:比较器先比第一关键字、相等再比第二关键字: → 1,1 1,2 2,1 2,2。正确答案 A。
实现要点:双关键字比较器 = if (x.a != y.a) return x.a < y.a; return x.b < y.b;(先主后次)。手算:先按第一关键字分组,组内按第二关键字排。
排除法:B 第二关键字排反;C 第一关键字排反;D 只在组内排了序、组间没排。
关联 · sort 函数与自定义比较器(F7):比较器是本题的载体。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[6] = {4, 1, 3, 2, 6, 5}; 05 priority_queue<int, vector<int>, greater<int>> q; // 小根堆 06 for (int i = 0; i < 6; i++) q.push(a[i]); 07 while (!q.empty()) { 08 cout << q.top() << " "; // 每次取当前最小 09 q.pop(); 10 } 11 return 0; 12}
单选题:程序输出是?
考点:堆排序的输出(N6)。
解析:小根堆每次取最小 → 1 2 3 4 5 6。正确答案 A。
实现要点:priority_queue<int, vector<int>, greater<int>> 是小根堆;升序 = 小根堆取顶、降序 = 大根堆(默认)。手算:想象每次弹出当前最小值。
排除法:B 是大根堆(默认)的输出;C 是原数组;D 前 5 个对、最后错位。
关联 · 堆排序的基本思想(F1):取堆顶 次即有序。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[7] = {0, 3, 8, 1, 9, 2, 7}; // a[0] 不用,下标 1~6 建大根堆 04int n = 6; 05void down(int x) { // 下沉调整:大元素上浮 06 int t = x; 07 if (2 * x <= n && a[2 * x] > a[t]) t = 2 * x; 08 if (2 * x + 1 <= n && a[2 * x + 1] > a[t]) t = 2 * x + 1; 09 if (t != x) { swap(a[t], a[x]); down(t); } 10} 11int main() { 12 for (int i = n / 2; i >= 1; i--) down(i); // 自底向上建堆 13 for (int i = 1; i <= n; i++) cout << a[i] << " "; 14 return 0; 15}
单选题:程序输出是?
考点:建堆后的数组(N7)。
解析:自底向上 down:处理 3 → {3,8,7,9,2,1};处理 2 → {3,9,7,8,2,1};处理 1 → 9 8 7 3 2 1(大根堆)。正确答案 A。
实现要点:建堆 = 从最后一个非叶节点(n/2)往前逐个 down。手算:自底向上每层调整,父子比较取大者上浮。注意堆序 ≠ 有序。
排除法:B 是排好序的结果(建堆不是排序);C 少下沉一步;D 最后两个次序错。
关联 · 堆排序的不稳定性(F3):建堆的隔层交换即不稳定来源。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[6] = {5, 1, 4, 2, 8, 3}; 05 int n = 6; 06 for (int i = 0; i < n - 1; i++) 07 for (int j = 0; j < ______; j++) 08 if (a[j] > a[j + 1]) swap(a[j], a[j + 1]); 09 for (int i = 0; i < n; i++) cout << a[i] << " "; 10 return 0; 11}
单选题:横线处应填入?
考点:补全冒泡内层(O1)。
解析:第 趟末尾 个元素已就位,内层比较范围 n - 1 - i(防越界 + 免比较已就位部分)。运行输出 1 2 3 4 5 8。正确答案 A。
实现要点:冒泡内层上界 = n - 1 - i:既保证 a[j+1] 不越界,又跳过末尾已就位的元素。
排除法:B(n-1)每趟都多比较已就位部分且末趟越界;C/D 同理且更糟。
关联 · 冒泡内层越界(P1):上界写错的第一后果是越界。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[6] = {5, 1, 4, 2, 8, 3}; 05 int n = 6; 06 for (int i = 0; i < n - 1; i++) { 07 int p = i; 08 for (int j = i + 1; j < n; j++) 09 if (______) p = j; 10 swap(a[i], a[p]); 11 } 12 for (int i = 0; i < n; i++) cout << a[i] << " "; 13 return 0; 14}
单选题:横线处应填入?
考点:补全选择查找(O2)。
解析:找 [i, n-1] 中最小值的下标,条件 a[j] < a[p]。运行输出 1 2 3 4 5 8。正确答案 A。
实现要点:选择内层 = 打擂台:比当前擂主 a[p] 更小才更新 p。方向写反(>)会变成降序(P2)。
排除法:B 是找最大值;C 条件与 i 无关;D 比较的是下标不是值。
关联 · 选择的基本思想(C1):打擂台找最小。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[6] = {5, 1, 4, 2, 8, 3}; 05 int n = 6; 06 for (int i = 1; i < n; i++) { 07 int key = a[i], j = i - 1; 08 while (______) { a[j + 1] = a[j]; j--; } 09 a[j + 1] = key; 10 } 11 for (int i = 0; i < n; i++) cout << a[i] << " "; 12 return 0; 13}
单选题:横线处应填入?
考点:补全插入内层(O3)。
解析:内层条件 j >= 0 && a[j] > key(先判界再比较)。运行输出 1 2 3 4 5 8。正确答案 A。
实现要点:短路求值顺序不能反:j >= 0 在前防越界;a[j] > key 决定"继续左移"。写成 a[j] < key 变降序(P3)。
排除法:B 方向反;C 只移相等元素(几乎不移动);D 缺越界判断会访问 a[-1]。
关联 · 插入排序输出结果(K1):同款框架的补全版。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int a[6] = {5, 1, 4, 2, 8, 3}; 04void qs(int l, int r) { 05 if (l >= r) return; 06 int pivot = a[l], i = l; 07 for (int j = l + 1; j <= r; j++) 08 if (a[j] < pivot) { i++; swap(a[i], a[j]); } 09 swap(a[l], ______); 10 qs(l, i - 1); 11 qs(i + 1, r); 12} 13int main() { 14 qs(0, 5); 15 for (int i = 0; i < 6; i++) cout << a[i] << " "; 16 return 0; 17}
单选题:横线处应填入?
考点:补全快排分区(O4)。
解析:循环后 a[i] 是最后一个小于基准的元素,基准与它交换落位 → 填 a[i]。运行输出 1 2 3 4 5 8。正确答案 A。
实现要点:分区最后一步 = swap(a[l], a[i]) 把基准放到"小于区"与"大于区"的分界处,之后 qs(l, i-1) / qs(i+1, r)。
排除法:B(a[l])等于自己换自己;C(a[r])把基准放错位置;D(a[pivot])把值当下标用。
关联 · 一次分区后的状态(L1):分区三步:收集小于 → 基准落位 → 递归。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[4] = {1, 3, 2, 4}; // 左半 [0,1] 与右半 [2,3] 各自有序 05 int tmp[4]; 06 int l = 0, mid = 1, r = 3; 07 int i = l, j = mid + 1, k = l; 08 while (i <= mid && j <= r) { 09 if (a[i] <= a[j]) tmp[k++] = a[i++]; 10 else tmp[k++] = a[j++]; 11 } 12 while (______) tmp[k++] = a[i++]; // 左半有剩余 13 while (j <= r) tmp[k++] = a[j++]; 14 for (int t = l; t <= r; t++) { a[t] = tmp[t]; cout << a[t] << " "; } 15 return 0; 16}
单选题:横线处应填入?
考点:补全归并合并(O5)。
解析:左半剩余时继续搬运,条件 i <= mid。运行:{1,3} 与 {2,4} 合并 → 1 2 3 4。正确答案 A。
实现要点:merge 两个收尾 while:i <= mid 搬左剩、j <= r 搬右剩——两段必有一段先耗尽。
排除法:B(i <= r)会把 tmp 的垃圾也搬进来;C(i < mid)漏搬最后一个;D 判断的是右指针。
关联 · 合并两个有序段(M1):收尾 while 是合并完整性保证。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 1, 4, 2, 3}; 05 int n = 5; 06 for (int i = 0; i < n - 1; i++) 07 for (int j = 0; j < n - i; j++) // 错误:应为 n - 1 - i 08 if (a[j] > a[j + 1]) swap(a[j], a[j + 1]); 09 for (int i = 0; i < n; i++) cout << a[i] << " "; 10 return 0; 11}
单选题:这段程序会?
考点:冒泡内层越界(P1)。
解析:第一趟 时 j < n - 0 = 5,j = 4 时访问 a[5]——数组只有 0~4,越界(未定义行为)。正确答案 A。
排除法:B 是正确上界的结果;C——越界不是"安全"的;D 能编译(运行时才越界)。
关联 · 补全冒泡内层(O1):正确上界
n - 1 - i。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[5] = {5, 3, 8, 1, 7}; 05 int n = 5; 06 for (int i = 0; i < n - 1; i++) { 07 int p = i; 08 for (int j = i + 1; j < n; j++) 09 if (a[j] > a[p]) p = j; // 错误:找最大放到前面 10 swap(a[i], a[p]); 11 } 12 for (int i = 0; i < n; i++) cout << a[i] << " "; 13 return 0; 14}
单选题:程序输出是?
考点:选择比较方向写反(P2)。
解析:> 变成找最大放到最前:8→首位、7→次位、5→第三位 → 8 7 5 3 1(降序)。正确答案 A。
实现要点:选择排序方向由 a[j] < a[p] 决定;写反 = 降序。检查口诀:升序找最小用 <。
排除法:B 是正确条件的升序;C 是原数组;D 是第一轮后的中间态。
关联 · 补全选择查找(O2):一个符号决定升降。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
01#include <bits/stdc++.h> 02using namespace std; 03int main() { 04 int a[4] = {3, 1, 4, 2}; 05 int n = 4; 06 for (int i = 1; i < n; i++) { 07 int key = a[i], j = i - 1; 08 while (j >= 0 && a[j] < key) { a[j + 1] = a[j]; j--; } // 错误:方向写反 09 a[j + 1] = key; 10 } 11 for (int i = 0; i < n; i++) cout << a[i] << " "; 12 return 0; 13}
单选题:程序输出是?
考点:插入比较方向写反(P3)。
解析:< 使比 key 小的元素后移,key 落到最前 → 每步把新元素顶到前面 → 4 3 2 1(降序)。正确答案 A。
实现要点:插入方向由 a[j] > key 决定;写反 = 降序。手算第一轮:key=1、3<1 不成立 → 1 留在原位;第二轮 key=4 把 1、3 都顶开 → 4 3 1 2。
排除法:B 是正确条件的结果;C 是原数组;D 是只跑了前两轮。
关联 · 插入的稳定性(D3):方向与稳定性共用同一个比较符。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:快排递归函数开头缺少 if (l >= r) return; 这个终止条件,会发生什么?
考点:快排缺递归边界(P4)。
解析:没有 if (l >= r) return;,空区间/单元素区间仍继续递归,深度无限增长 → 栈溢出。正确答案 A。
排除法:B——单元素区间里分区后仍会自调用,不是"结果正确";C 能编译;D 与"只排一次"无关。
关联 · 快排递归输出(L2):终止条件是递归的命门。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:归并排序合并循环里,把写入辅助数组的 tmp[k++] 误写成 tmp[i++],后果是?
考点:归并下标写错(P5)。
解析:tmp[i++] 用读取指针 i 去写辅助数组,写入位置与读取位置冲突(i 还被用于比较),合并结果错乱。正确答案 A。
排除法:B 错——写入与读取互相干扰;C 无依据;D 能编译(逻辑错误不报错)。
关联 · 合并两个有序段(M1):i/j 是读取指针,k 是写入指针,各司其职。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。
单选题:计数排序中统计数组 cnt[5](下标 ),而数据里出现了值 ,执行 cnt[a[i]]++ 会?
考点:计数数组越界(P6)。
解析:cnt[5] 只有下标 0~4,值 5 使 cnt[5]++ 越界——访问数组外内存,行为未定义。正确答案 A。
排除法:B——C++ 数组不自动扩容;C 不会忽略;D 能编译(运行时才越界)。
关联 · 计数排序的适用与稳定(F6):计数数组大小 = 值域上限 + 1。
大纲注:本细节属提高级大纲【5/6】,按用户教学规划保留(J 复赛必备扩展)。