下面代码使用插入排序将数组按升序排列,横线处应填写( )。
void insertionSort(int a[], int n) {
for (int i = 1; i < n; i++) {
int key = a[i];
int j = i - 1;
while (j >= 0 && __________) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = key;
}
}插入排序的核心是:把当前元素 key 插入到前面已排好序的子数组中。插入位置由比较决定——只要 a[j] 比 key 大,就往后挪一位,直到遇到比 key 小的元素或到达数组开头。因此循环条件必须判断 a[j] > key,这样才能保证最终 key 落在正确位置。
A 项 a[j] < key 会往后挪比 key 小的元素,导致 key 被挤到前面,破坏升序;C 项 a[j] == key 只在相等时移动,若遇到更小的元素就停止,key 会停在错误位置;D 项 a[j+1] > key 访问的是已移动后的位置,逻辑混乱且可能越界。命题人故意用这些看似合理的比较式来测试对排序过程的理解。
本题考查《GESP 考试大纲》四级"算法基础"模块中的排序算法知识点。命题人专门设置这道题,就是要卡住那些只背过"插入排序"四个字,却从未真正理解其执行流程的考生——他们看到 while 循环就下意识填"<",因为"升序"两个字在脑子里自动关联到"小于"。
看到 while 循环,先想:这个循环在做什么?它在把 key 往左挪,直到找到合适位置。那什么时候停?停的条件是"遇到比 key 小的元素"或"走到数组开头"。用代码表达就是:只要 a[j] > key,就继续挪;否则停下。
关键数字推演:假设 a = [5, 3, 4],i=1 时 key=3,j=0。若填 a[j] > key,则 5>3 成立,a[1]=5,j=-1,循环结束,a[0]=3,正确。若填 a[j] < key,则 5<3 不成立,循环直接结束,a[1]=3,数组变成 [5,3,4],错误。
这一类题的通法是:先明确循环在"移动谁",再想"移动到什么时候停",最后用比较式表达"不停止的条件"。
A 项 a[j] < key:命题人利用"升序=小于"的直觉误导,让考生误以为要往后挪小的元素。 C 项 a[j] == key:利用"相等也要处理"的过度思考,但插入排序遇到相等时应该停止,否则会把 key 挤到前面。 D 项 a[j+1] > key:偷换概念,把比较对象从当前元素 a[j] 换成下一个位置 a[j+1],逻辑完全混乱且可能越界。
如果把题目改成"降序排列",横线处应填 a[j] < key,因为此时要往后挪比 key 小的元素。 如果把 key 改成 a[i+1],整个算法就变成选择排序的雏形,循环条件要相应调整。 最阴险的变体是去掉 j>=0 判断,只留 a[j] > key,这样当 j=-1 时访问 a[-1] 越界,考察边界条件意识。