第 15 题
答案与解析
第(2)小题
D
解题思路
函数在一趟循环中比较相邻影片,必要时交换;随后递归处理前n−1项,使比较范围逐次缩小。这是用递归控制趟数的冒泡排序。比较的是下标3所存的综合得分,左侧得分较低时交换,因此较低得分向右移动。
程序分析
if n < 2: #语句1
return b当前待处理部分不足2项时,不需要再比较相邻元素,直接返回列表。这是递归的终止条件。
for i in range(n - 1):
if b[i][3] < b[i + 1][3]:
b[i], b[i + 1] = b[i + 1], b[i]i从0增至n−2,逐对比较相邻影片;若左侧得分更低,就交换整条影片记录。每次比较后,较低得分留在右侧,继续参与下一次比较。因此一趟结束时,前n项中的最低得分被送到下标n−1的位置。
return fsort(b, n - 1)本趟已确定末项的位置,递归只处理前n−1项,再将其中最低分送到该部分的末尾。如此逐步缩小范围,最终得到按综合得分从高到低排列的列表,各层直接返回递归所得列表。
选项分析
第(3)小题
lst[pre][4] = lst[p][4]
seat == lst[p][2] and lst[p][3] > 1
lst[p][3] = seat - lst[p][1]
程序分析
lst = [[0,0,0,0,1]] #lst[0][4]指向头节点
for i in range(1,row+1):
lst.append([i,1,tot,tot,i+1]) #构造链表,初始化每排可选座位区间
lst[-1][4] = -1主程序用列表模拟链表,每个区间结点依次存储[排数,起始座位号,终止座位号,可选座位数,后继下标]。lst[0]是表头入口记录,lst[0][4]保存首个有效区间的下标;各结点下标4处保存后继下标,−1表示没有后继。初始化时,每排对应一个[1,tot]区间,各排依次连接。区间的逻辑顺序由这些链接决定。
for info in data:
if info[3] == "购票":
order_seat(info[1],info[2],lst)
else:
add_seat(info[1],info[2],lst)data已按时间升序排列,程序依次处理购票、退票事件。购票时将info[1]的座位号和info[2]的排号传入order_seat,因此函数参数seat表示待购座位号,row表示本次购票的排号;主程序初始化时的row表示影厅总排数。
pre = 0
p = lst[pre][4]
while p != -1 and lst[p][0] != row:
pre = p
p = lst[p][4]p从首个有效区间开始,沿lst[p][4]保存的后继下标查找。每轮先令pre = p,再令p = lst[p][4],使pre跟在p之前,保存当前结点的前驱下标。循环遇到目标排的第一个区间时停止。
while p != -1 and lst[p][0] == row:
...
pre = p
p = lst[p][4]在目标排内依次检查区间,根据seat位于区间的哪个位置选择处理分支。末尾沿当前结点的后继继续扫描,直到到达链尾或进入其它排。一次购票只会落在一个有效区间中。
if seat == lst[p][1] and lst[p][3] == 1:
①
elif seat == lst[p][1] and lst[p][3] > 1:
lst[p][1] = seat+1
lst[p][3] -= 1两个分支都要求seat等于区间起点,再按可选座位数是否为1分开处理。第二个分支已有的语句把起点改为seat+1,并将座位数减1,保留右侧的可选区间。
elif ②:
lst[p][2] = seat-1
lst[p][3] -= 1该分支已有的语句将终点改为seat−1,并将可选座位数减1,起点保持不变。
elif seat > lst[p][1] and seat < lst[p][2]:
right = lst[p][2]
lst[p][2] = seat-1
③
lst.append([row,seat+1,right,right-seat,lst[p][4]])
lst[p][4] = len(lst)-1seat严格位于区间内部时,right先保存原终点,原结点的终点改为seat−1,留下左半段。随后追加右半段[seat+1,right],座位数为right−seat,其后继先取原结点的后继。最后将原结点的后继改为新结点下标len(lst)−1,形成“左半段→右半段→原后继”的链接。
填空分析
①
空①所在分支对应区间中只有一个座位且该座位被购买的情况,需要从有效链表中删除当前结点。lst[pre][4]保存前驱的后继下标,lst[p][4]保存当前结点的后继下标;让前驱直接连接当前结点的后继,填写:
lst[pre][4] = lst[p][4]
删除首个有效结点时pre为0,这一语句更新表头入口;删除链尾时,原后继为−1,这一语句使前驱成为链尾。这里只修改链接,保留lst中的存储位置,避免其他结点下标改变。
②
该分支保留原起点,将终点改为seat−1且座位数减1,因此对应购买区间最右端的座位。单座位区间已由前面的分支处理,可同时写明本分支处理多个座位的情况:
seat == lst[p][2] and lst[p][3] > 1
③
执行到空③时,原结点的终点已变为seat−1,起点lst[p][1]不变,但座位数尚未更新。按“终点−起点+1”,左半段的数量为(seat−1)−lst[p][1]+1,因此填写:
lst[p][3] = seat - lst[p][1]
也可直接利用已更新的终点,写成lst[p][3] = lst[p][2] - lst[p][1] + 1。
第(1)小题
[1,4]
[6,7]
[9,10]
本小题按源试卷表格读取记录:四条记录的排数均为5,座位号依次为3、5、3、8。
初始时第5排的可选区间为[1,10]。购票时移除对应座位,退票时恢复对应座位,并与相邻可选区间合并。
| 时间 | 第5排的操作 | 操作后的可选座位区间 |
|---|---|---|
| 初始 | 全部可选 | [1,10] |
| 08:37 | 3号购票 | [1,2]、[4,10] |
| 08:50 | 5号购票 | [1,2]、[4,4]、[6,10] |
| 09:00 | 3号退票 | [1,4]、[6,10] |
| 09:12 | 8号购票 | [1,4]、[6,7]、[9,10] |
09:00恢复的3号连接左侧[1,2]和右侧[4,4],合并为[1,4];09:12购买8号后,[6,10]拆为[6,7]和[9,10]。此后至09:15没有新的记录,因此保留表中最后一行的区间。
问题反馈
解析有疑问或显示异常?请先复制题目信息,再打开反馈表单填写。
题目编号:2026_04_G3_ningboermo_q015
