夜雨聆风学习资料网

ARTICLE · 1122430

开学考的这一题,值得一做!最坑的代码填空是这一句?

开学考的这一题,值得一做!最坑的代码填空是这一句?
最近,全省各地的开学考都在陆续进行中,其中七彩阳光开学考信息选择的最后一题,考到了一个排序算法的变形——双向选择排序,坑到了不少同学。
普通的选择排序大家都见过,每轮找一个最小值放到前面。但双向选择排序不一样——它每轮同时找最小值和最大值,分别放到左右两端。
今天这篇文章,朱老师就带大家把双向选择排序彻底拆解清楚,希望同学们看完之后能够有所收获~

【例】某升序排序算法,其Python程序段如下:

# 随机产生n个整数存入列表a,代码略n = len(a)for i in range(n // 2):    minid = i    maxid = i    for j in range(____(1)____):        if a[j] < a[minid]:            minid = j        if a[j] > a[maxid]:            maxid = j    a[i], a[minid] = a[minid], a[i]    if i == maxid:        ____(2)____    ____(3)____

代码中(1)~(3)处可选的表达式有:

① i + 1, n - i - 1② i + 1, n - i③ a[n - i - 1], a[maxid] = a[maxid], a[n - i - 1]④ a[n - i], a[maxid] = a[maxid], a[n - i]⑤ maxid = minid ⑥ minid = maxid

要使程序实现上述排序算法功能,则(1)~(3)处的表达式序号依次为:

A. ②⑤③ 

B. ①⑤③    

C. ①⑥④    

D. ②⑥④

01
算法模型
双向选择排序:
每一轮在当前未排序区间里,同时找出最小值和最大值,把最小值扔到最左边、最大值扔到最右边,然后左右边界各往里缩一位。

01

代码模型

arr = [6, 8, 5, 3, 9, 7]n = len(arr)i = 0          # i是当前未排序区间的左边界j = n - 1      # j是当前未排序区间的右边界while i < j:    mi = i     # mi记录本轮最小值的索引,先初始化为左边界    mx = i     # mx记录本轮最大值的索引,先初始化为左边界    # 在i到j之间遍历,找最小值和最大值的位置    for k in range(i, j + 1):        if arr[k] < arr[mi]:            mi = k       # 找到更小的,更新最小值索引        if arr[k] > arr[mx]:            mx = k       # 找到更大的,更新最大值索引    # 把最小值换到最左边i的位置    arr[i], arr[mi] = arr[mi], arr[i]    # 关键细节:如果最大值原本就在i位置,    # 上面交换后最大值被移到了mi的位置,所以要修正mx    if mx == i:        mx = mi    # 把最大值换到最右边j的位置    arr[j], arr[mx] = arr[mx], arr[j]    # 左右边界各往里缩一位,继续下一轮    i = i + 1    j = j - 1print(arr)

02

步骤拆解

①用 i 和 j 两个指针标记当前未排序区间的左右边界。
②遍历 i 到 j之间的元素,用 mi 和 mx 记录这轮找到的最小值和最大值的下标。
③先交换最小值到 i 位置。
④再交换最大值到 j 位置。
⑤i 往右移,j 往左移,重复直到 i >= j。

03

动画演示

哎嗨~ 看来这个双向选择排序的过程还是so easy的嘛~

Q

在第二轮的排序当中,最大值正好就在i位置,也就是mx==i,在完成arr[i]的 arr[mi]交换之后,最大值就被搬到了mi的位置:

接下来,要把最大值换到j的位置,如果直接执行arr[j]和 arr[mx]交换的语句,就会导致错误:
所以,我们要抓住问题的关键,进行针对性的解决。
 对于最大值正好就在i位置,交换之后被搬到了mi的的情况,需要增加语句“找补”一下:
# 如果最大值原本就在i位置    # 上面交换后最大值被移到了mi的位置,所以要修正mx    if mx == i:        mx = mi    # 把最大值换到最右边j的位置    arr[j], arr[mx] = arr[mx], arr[j]
既然最大值实际在mi那里,那把mx修正为mi位置就行啦~
02
解题思路
# 随机产生n个整数存入列表a,代码略n = len(a) for i in range(n // 2):  # 每轮能确定最小值和最大值,外层循环执行n//2趟   minid = i      # minid记录未排序区间最小值的下标   maxid = i     # maxid记录未排序区间最大值的下标   for j in range(____(1)____):    # j遍历未排序区间内剩下所有元素      if a[j] < a[minid]:         # 如果当前j位置元素,比记录的最小值还要小         minid = j               # 更新最小值下标minid为j      if a[j] > a[maxid]:         # 如果当前j位置元素,比记录的最大值还要大         maxid = j               # 更新最大值下标maxid为j   a[i], a[minid] = a[minid], a[i]      # 将找到的最小值交换到未排序区间最左边的位置i# 特殊情况:最大值原来就在左边界i,刚刚交换后最大值被移到minid位置   if i == maxid:                        ____(2)____                # 需要修正最大值下标,把maxid更新为minid   ____(3)____                    # 将找到的最大值交换到未排序区间最右侧的位置
了解双向选择排序的算法模型后,我们再来看代码要填的空:
(1)内层循环的范围
minid和maxid都初始化为i,所以j从i+1开始遍历,要包含排序范围内的所有值,也就是到右边界n-i-1结束。
注意range是左闭右开的,要包含到n-i-1,结束值就得写n-i,填range(i+1, n-i),对应②。
(2)if i == maxid 时的修正
先执行了 a[i], a[minid] = a[minid], a[i],把最小值换到了i位置。
如果最大值原本就在i位置(maxid==i),交换后最大值被移到了minid的位置。
所以,要把maxid修正为minid。填maxid = minid,对应⑤。
(3)把最大值换到右边
最右边的位置是n-i-1(第i轮,从右数第i个位置),把maxid位置的最大值和n-i-1位置交换。
填a[n - i - 1], a[maxid] = a[maxid], a[n - i - 1],对应③。
三个空分别是②⑤③,选A走人~
篇幅有限,如果同学们想深入学习各种排序算法的变形,滴滴一下,朱老师带你拿下它们~
后台回复:20261004
即可获得视频讲解

关注公众号

获取技术试题及优质干货

— 推荐阅读 —
【新高三秋季课程】二轮进阶刷题直播课程目录及上课流程!主讲:朱一帆老师
【27届新高三】技术首考冲刺一轮复习来了!主讲:朱一帆老师
【高二重难点】选修技术课程目录及上课流程!主讲:朱一帆老师
【新高二】必修技术教材课程目录及上课流程!主讲:朱一帆老师
【慎点】2026年技术选考不是玄学,数万名考生亲测有效!

相关学习资料