二、 链表及其基本操作课时练(学生版+教师版) 2025-2026学年高中信息技术 选择性必修1 数据与数据结构

资源下载
  1. 二一教育资源

二、 链表及其基本操作课时练(学生版+教师版) 2025-2026学年高中信息技术 选择性必修1 数据与数据结构

资源简介

(共39张PPT)
二、 链表及其基本操作
第二章 数组与链表
信息技术 选择性必修1 数据与数据结构
必备知识练
1. 使用链表结构模拟某校浏览路线,链表a中每一个节点包含三个数据,第1个为地点名称,第2个为预计停留时间(单位:分钟),第3个为指向下一个地点的指针。可以从多个地点开始浏览,但只能从“南大门”离开,输出显示从各景点进入路线及预计总时间的代码如下。
a=[["校训石",15,2],["教学楼",30,2],["风雨操场",25,5],["科技楼",40,4],["新华书店",60,5],["南大门",20,-1]]
head=[0,1,3]
for i in range(len(head)):
   (1)
  s=a[p][1]
  while a[p][2]!=-1:
    print(a[p][0],end="→")
     (2)
     (3)
  print(a[p][0])
  print("预计时间:",s,"分钟")
上述程序画线处的可选代码有:
①p=head ②p=head[i] ③s=s+a[p][1] ④p=a[p][2]
则(1)、(2)、(3)处代码依次为(  )
A.①③④ B.①④③
C.②③④ D.②④③
【解析】 本题考查链表节点遍历知识。由代码可知,p为当前节点,且起始节点可选,因此(1)处代码应该是p=head[i],从而排除选项A和B。代码(2)和(3)处,由于s的初值已经包含当前节点的访问时间(s=a[p][1])但却没有输出当前节点的地点名称,因此应该先指向下一个节点,然后再将该节点的访问时间累加到s中,即先④再③,故选D。
D
2. 使用列表d模拟链表结构(节点数大于0),每个节点包含数据区域和指针区域,h为头指针。下列程序段实现了删除数据区域为奇数的节点。
q=p=h=2
while p!=-1:
  if d[h][0]%2==1:
    (1)
   q=p=h
  elif d[p][0]%2==1:
    (2)
   p=d[p][1]
  else:
    q=p
    p=d[p][1]
画线处可选代码如下:
①h=d[h][1] ②p=d[p][1] ③d[p][1]=d[q][1] ④d[q][1]=d[p][1]
下列选项中,代码顺序正确的是(  )
A.①③ B.②③
C. ①④ D.②④
【解析】 本题考查链表节点删除知识。由代码可知,p为当前节点,q为p的前驱节点,删除当前节点p的代码应该是d[q][1]=d[p][1],因此可以排除③,即选项AB不可能。h为头节点,需要单独考虑,若头节点为奇数则删除头结点h,且修改头节点的值,因此(1)处代码为h=d[h][1],故本题选C。
C
3. 用链表实现数组的升序排序,Python程序如下,方框中应填入的正确代码是(  )
#生成无序数组,元素如[3,-1],分别表示数值和指针(指针初值均为-1),代码略
head=0
for i in range(1,len(a)):
  q=head
  p=a[head][1]
  if a[head][0]>a[i][0]:
    a[i][1]=head
    head=i
  else:
          
    a[q][1]=i ; a[i][1]=p
A. while p!=-1 and a[p][0]  q=p
  p=a[p][1]
B. while p!=-1 and a[p][0]  p=a[p][1]
  q=p
C. while p!=-1 and a[q][0]  p=q
  q=a[q][1]
D. while q!=-1 or a[p][0]  q=p
  p=a[p][1]
A
【解析】 本题考查链表与排序的综合应用。该算法中head固定在位置0,每轮均需要在已完成排序的链表中遍历,并把a[i]插入到q和p之间。本轮查找时,若p节点数据小于a[i]并且未到链表尽头(p不等于-1),则继续搜索,然后更新前置节点q和后继节点p。A正确。
4. 使用列表d模拟链表结构(节点数大于0),每个节点包含数据区域和指针区域,head为头指针。现要删除链表中数据值在[begin,end]范围的节点,实现该功能的部分程序段如下,
方框中应填入的代码是(  )
d=[[4, 5], [10, 2], [12, 4], [1, 0], [16, -1], [7, 1]]
head=3
q=head;p=head
while p!=-1:
  if d[p][0]end:
    q=p
    p=d[p][1]
else:
A. if head!=p:
  d[q][1]=d[p][1]
else:
  head=d[p][1]
p=d[p][1]
B. if head==p:
  d[q][1]=d[p][1]
else:
  head=d[p][1]
p=d[p][1]
C. if head!=p:
  p=d[p][1]
else:
  head=d[p][1]
p=d[p][1]
D. if head==p:
  p=d[p][1]
else:
  head=d[p][1]
  p=d[p][1]
A
【解析】 本题考查链表节点删除的知识。根据代码可知,p为当前节点,q为p的前驱节点。其删除数据节点的逻辑为:若数值不在[begin,end]范围之内的节点p,依次往后进行迭代。若数值在[begin,end]范围之内的节点p,将当前节点删除。删除节点p时又可分为两种情况,若删除的是头节点,需要更新head值为当前节点p的下一个节点,代码为head=d[p][1]。若删除的节点不是头节点,则让p的前驱节点q直接指向p的后继节点,即可实现删除p节点,因此其代码是d[q][1]=d[p][1]。A正确。
关键能力练
5. 使用列表d模拟链表结构(节点数大于2,且不存在连续为0的节点),每个节点包含数据区域
和指针区域,h为头指针。链表的开头和末尾的节点数据区域的值均为0,如图1所示。现要把
相邻两个数值为0的节点之间所有节点合并为一个节点,该节点值为所有合并节点值之和,并
将值为0的节点移除,结果如图2所示。实现该功能的部分程序段如下,方框中应填入的正确代
码是(  )
k=h;p=d[k][1]
while k!=-1 and p!=-1:
       
  p=d[k][1]
图1
图2
A. if d[p][0]!=0:
  d[k][0]+=d[p][0]
d[k][1]=d[p][1]
if d[p][0]==0:
  k=p
B. if d[p][0]!=0:
  d[k][0]+=d[p][0]
d[k][1]=d[p][1]
if d[p][0]==0:
  k=d[k][1]
C. if d[p][0]==0:
    k=p
else:
  d[k][0]+=d[p][0]
  d[k][1]=d[p][1]
D. if d[p][0]==0:
  k=d[k][1]
else:
  d[k][0]+=d[p][0]
  d[k][1]=d[p][1]
B
【解析】 本题考查链表操作等相关知识。题干明确告知头节点和尾节点数据区域均为0,因此从第一个节点开始就需要将后继的值加入当前头节点的数据域当中,并删除值已经被加入的节点。而当下一次遇到数值为0的节点时,就需要思考,最后一个节点也是数据为0的节点,如果按照如上的方案进行后几个0节点的操作,那么最后一个0节点将无法被删除。因此,当跳过第一个0节点以后,当遇到下一个0数据域的节点时,直接跳过当前节点,以0数据域的下一个节点作为当前 k的节点,既保证了数据域的不丢失,也保证了删除数据域为 0 的节点。A选项,当碰到数据域的0节点时,k移动到当前0节点数据域,但是当前的节点在上一次的使用中已经被删除,A错误。当碰到数据域的0节点,k 移动到当前0节点数据域,最后一个0节点无法被删除,C、D错误。
6. 使用列表d模拟链表结构(节点数大于1),每个节点包含数据区域(数据均为整型,范围为0~9)和指针区域,h为头指针,如图1所示。现要对该链表节点进行去重操作,只保留最后一次出现的节点,结果如图2所示。
lst = [0]*10
p = h
while p != -1:
  lst[d[p][0]] += 1
  p = d[p][1]
q, p = h, h
while d[p][1] != -1:
         
  p = d[p][1]
图1
图2
A. if lst[d[p][0]] >= 2:
 if p == h:
   h = d[h][1]
 else:
   d[q][1] = d[p][1]
   lst[d[p][0]] -= 1
else:
   q = p
B. if lst[d[p][0]] < 2:
 q = p
elif p == h:
  lst[d[p][0]] -= 1
  h = d[h][1]
else: 
  lst[d[p][0]] -= 1
  d[q][1] = d[p][1]
C. if lst[d[p][0]] >= 2:
 if p == h:
   h = d[h][1]
 else:
   d[d[p][1]][1] = q
   lst[d[p][0]] -= 1
else:
   q = d[q][1]
D. if lst[d[p][0]] < 2:
  q = d[p][1]
else:
  if p != h: 
    d[q][1] = p
  else:
    h = d[h][1]
  lst[d[p][0]] -= 1
实现该功能的程序段如下,方框中应填入的代码是(  )
B
【解析】 本题考查链表的综合应用。删除链表的重复元素,先通过遍历将链表元素按数值放入 lst 数组中,lst 数组实现统计每个元素出现的次数。若次数小于 2 ,则保留,若大于或等于2,则通过链表元素删除,保留最后一次出现的节点。删除链表节点分为两种情况:①删除头节点,通过修改头指针为 h=d[h][1]实现;②删除非头指针,q 为前驱节点,p 为当前节点,通过修改前驱节点指针域d[q][1]=d[p][1],删除当前 p 指向的节点。 B正确。
7. 有如下Python程序段:
a=[[1,1],[2,2],[3,3],[4,-1]]
head=0
cur=a[head][1]
a[head][1]=-1
while cur!=-1:
  next=a[cur][1]
  a[cur][1]=head
  head,cur=cur,next
则程序执行后,a的值为(  )
A.[[1,1],[2,2],[3,3],[4,-1]] B.[[1,-1],[2,0],[3,1],[4,2]]
C.[[4,1],[3,2],[2,3],[1,-1]] D.[[4,-1],[3,0],[2,1],[1,2]]
【解析】 本题考查链表操作知识。该程序通过修改各个节点的指针值,来实现链表全部节点逆转的功能。程序运行结束后head的值为3,结果如选项B。
B
8. 使用列表L模拟链表结构,每个节点包含数据区域和指针区域,现要删除该链表中的某一元素,示例输出结果如图所示,实现该功能的程序段如下。
请输入要删除的数据:9
找到删除数据
7->4->8->6->5
>>>
==============RESTA
==
请输入要删除的数据:18
未找到删除数据
9->7->4->8->6->5
>>>
def delete(data,p):
  head=0
  if p==data[head][0]:
    head=data[head][1]
    print("找到删除数据")
  else:
    cur=pre=head
    while (1) :
      pre=cur
      cur=data[cur][1]
    if cur!=-1:
       (2)
      print("找到删除数据")
    else:
      print("未找到删除数据")
    return head
L=[[9,3],[4,2],[8,4],[7,1],[6,5],[5,-1]]
key=int(input("请输入要删除的数据:"))
head=delete(L,key)
#输出删除后的结果程序省略
画线处应填入的代码依次是(  )
①data[cur][0]!=p and data[cur][1]!=-1
②data[cur][0]!=p and cur!=-1
③data[pre][1]=data[cur][1]
④data[cur][1]=data[pre][1]
A. ①③ B. ①④
C. ②③ D. ②④
C
【解析】 本题考查链表的基础操作知识。(1)处要完成的功能是,若当前节点cur的值不等于要删除的数p,且当前节点不是尾节点时,依次往下遍历,实现过程是迭代,即先将当前节点cur赋值给前驱节点pre,然后cur继续往下走一步,因此在①②代码中,②的表达式正确。(2)处实现的功能是,若找到需要删除的数据,且该节点不是尾节点时删除当前节点。分析代码可知,cur是当前节点,而pre是cur的前驱节点,因此删除的数据的正确代码是前驱节点pre直接指向当前节点cur的后继节点data[cur][1],即data[pre][1]=data[cur][1],因此在③④中选择③。C正确。
9. 给定一个链表a,以表头元素为基准数,将小于基准的节点移动到它的左侧,且保持节点相对顺序不变;大于基准的节点保持不动。如图1所示的链表处理后的结果如图2所示。实现该功能的程序段如下,head为头指针。
pivot = a[head][0]
p, r = head, -1
while a[p][1] != -1:
  q = a[p][1]
  if a[q][0] < pivot:
    a[p][1] = a[q][1]
            
    r = q
  else:
    p = a[p][1]
图1  
图2  
A. if r == -1:
 a[q][1]=p
 head=q
else:
 a[r][1]=a[q][1]
 a[q][1]=r
B. if r == -1:
 a[p][1]=q
 head=q
else:
 a[r][1]=a[p][1]
 a[q][1]=r
C. if r == -1:
 a[p][1]=q
 head=q
else:
 a[q][1]=a[r][1]
 a[r][1]=q
D. if r == -1:
 a[q][1]=head
 head=q
else:
 a[q][1]=a[r][1]
 a[r][1]=q
则方框中应填入的代码是(  )
D
【解析】 本题考查链表知识。第5行元素值的比较可以看出,q节点表示当前待移动的节点,p节点是它的前一个节点。第6行相当于让q的前一个节点指向q的后一个节点,即跳过了q节点。第8行程序让r指向q节点,而q是最后一次移动的节点,因此r可以看成左侧链表的尾节点。第10行是q节点的值大于等于基准的情况,这时p直接往后移一位,那么p就是基准右侧链表的最后一个节点。对于四个选项的条件都是r为-1的情况,即r还未指向任何一个节点,也相当于左侧链表为空的情况。这时可以让q节点的下一个节点指向右侧节点的第一个节点,即p或者head节点(如选项A和D所示)。当r指向一个实际元素时,新元素应该如何插入 放在r的前面还是r的后面 这也是选项A和选项D中“else”分支语句的差别。考虑到题目中要求元素移动后保持相对顺序不变,后插入的元素应该在前插入的元素后面,因此元素应该插在r的后面。选项A将q节点插在了r的前面。选项D将q节点插在了r的后面,D正确。选项B和C,在if分支中的逻辑与第6行程序有冲突。
10. 有如下Python程序段:
a=[[1,3],[1,0],[7,1],[4,5],[1,-1],[6,4]]
x=1
p=head=2
if x==a[p][0]:
  head=a[p][1]
else:
  while p!=-1:
    if x==a[p][0]:
      a[pre][1]=a[p][1]
    else:
      pre=p
    p=a[p][1]
运行该段程序后,a[2][1]的值为(  )
A. -1 B. 0
C. 1 D. 3
【解析】 本题考查链表的遍历及删除节点操作。阅读代码可知,选择结构部分的操作为:当x为当前链表头指针所指的节点的数据,那就删除头节点,如果不是就遍历后续节点并删除数据域为1的节点。因为删除需要记录当前节点的前驱节点,使用pre来存储。原链表为7→1→1→4→6→1。故删除了数据域为1的节点之后,数据7直接指向了数据4,故a[2][1]为3,D正确。
D
11. 使用列表d模拟链表结构(节点数大于1),每个节点包含起始数值、连续长度、指针区域,h为头指针。链表中各节点已按起始数值由小到大排列,各个节点表示的数值区间不重叠,例如链表d为[[20, 100, 3], [150, 50, 2], [250, 60, -1], [120, 30, 1]],h=0,其中节点 [20, 100, 3]表示从数值20开始有长度为100的连续值(20到119),3代表后继节点索引为3,现要合并链表各节点连续的数值区间,合并后链表d的数据修改为[[20, 180,2], [150, 50, 2], [250, 60, -1], [120, 30, 1]],h=0。实现该功能的Python程序段如下。
q=h=0
p=d[q][2]
while p!=-1:
  if d[p][0]==d[q][0]+d[q][1]:
    d[q][1]=d[q][1]+d[p][1]
  else:  
   (1) 
   (2) 
   (3) 
上述程序中方框处可选语句如下:
①q=p ②d[q][2]=p ③p=d[p][2]
加框处的代码依次是(  )
A. ①、②、③ B. ①、③、②
C. ②、①、③ D. ②、③、①
【解析】 本题考查链表的基础知识。分析代码可得,p是当前节点,q是p的前驱节点。如果q、p指向链表相邻两个节点的数值区间连续,则将两个节点进行合并,更新q节点的连续长度(即q节点的连续数值长度加上p节点的连续数值长度)。同时q节点的指针域需要指向当前p节点的后继节点。否则,将指针q的值更新为p,指针p后移指向下一节点。B正确。
B
12. 链表a中各节点由数据域和指针构成,并按数据域数值升序排列(头节点数据为奇数),现要修改各节点顺序,按奇数在前升序、偶数在后升序的顺序排列,如图所示。实现该功能的程序段如下。
a = [[8,1],[9,-1],[6,0],[1,5],[5,2],[2,4]]
p = t = head = 3
while a[t][1] != -1:
  k = a[t][1]
  if a[k][0] % 2 == 1:
            
  else:
    t = a[t][1]
A. a[t][1] = a[p][1]
a[p][1] = t
p = t
t = k
B. a[t][1] = a[k][1]
a[k][1] = a[p][1]
a[p][1] = k
p = a[p][1]
C. a[p][1] = t
a[t][1] = a[p][1]
p = a[p][1]
t = k
D. t = a[t][1]
a[k][1] = a[p][1]
a[p][1] = k
p = k
【解析】 本题考查链表操作。本题的重点是理解几个指针的作用:p,t从头节点(奇数)出发,k为t的后继,若a[k][0]为偶数,则t指针后移……直到a[k][0]为奇数时才停止,此时t为连续偶数的最后一个,接下来从原位置删除k点(a[t][1]=a[k][1])。将k点连接到p之后:a[k][1]= a[p][1];a[p][1]=k。p指针后移,保留奇数段的链尾:p=a[p][1]。B正确。
则方框中应填入的代码是(  )
B
13. 利用链表实现升序排序:二维列表a同时保存数据域和指针域,排序的过程就是将每个数据的指针域不断链接到已有的有序链表的合适位置,直到所有的数据均链接到链表中。
例如,将某节点插入到已有链表中,根据大小比较有三种情况:插入到最前面、插入到最后、插入到中间。具体程序设计方法如下:
①将待排序的n个数保存在列表a中,且指针域的值均为-1,形成n个没有链接的节点。
②将每个节点看成只含有一个节点的链表head,且head=0。
③将第i个节点插入到链表head的适当位置,使head仍有序,此时head成为含有两个节点的有序链表;以此方法依次将a列表中的其他节点插入到链表head中,最后链表head上包含所有节点,且节点有序。依次输出head链表的数据域即可完成排序。
程序运行界面如图所示,采用此思想进行升序排序的Python代码如下,请回答下列问题:
原始链表为:[[43,-1],[68,-1],[25,-1],[17,-1],[52,-1]]
排序后链表:[[43,4],[68, -1],[25,0],[17,2],[52,1]]
排序后数据:17 25 43 52 68
#随机生成列表a的数据域的值,且指针域全部为-1,代码略
n = len(a)
print("原始链表为:",a)
head=0
for i in range(1,n):
 ①_____________
 if a[k][0]>=a[i][0]:
   a[i][1]=k
   head=i
 else:
   while a[i][0] > a[a[k][1]][0] :  #改错
     k = a[k][1]
   a[i][1] = a[k][1]
   ②____________
print("排序后链表:",a)
print("排序后数据:",end=" ")
k=head
while k != -1:
  print(a[k][0],end=" ")
 ③______________
k=head
a[k][1]=i
k=a[k][1]
(1)若用该算法进行升序排序,a=[[46, -1], [19, -1], [10, -1], [37, -1]],排序完成后,head变量的值为__________。
(2)为实现上述功能,请在画线处填入合适的代码。
(3)加框处代码有错误,请改正。
【答案】 a[i][0]> a[a[k][1]][0]and a[k][1]!=-1
【解析】 本题考查链式存储的插入排序算法。(1)链表是通过head进行遍历数据,升序排序时,最小值下标为2,故head值为2。(2)①此处表示插入的节点位于最前面的情况,故答案是k=head,为了避免head的值发生改变,因此使用k模拟head指针。②此处寻找插入位置,若插入数据a[i][0]大于当前值,则找下一个节点,直到到达链表的最后一个节点,若找到位置,则先更新i的下一个为k的下一个,再更新k的下一个为i节点(顺序不可更改)。③此处通过k(相当于head)遍历整个链表,并输出数据域,下一个节点的位置是k=a[k][1]。(3)否则继续循环每个节点,将节点i和当前遍历节点k的下一个节点进行比较,所以找到的k为第一个大于i的节点的前一个节点。除了考虑比较大小外,还必须考虑a[k][1]的值不能为-1(-1表示尾部)。
2
14. 某花瓶厂有三台不同型号的机器,可生产ABC三种不同型号的花瓶。厂家每天会收到很多网上订单,每个客户的订单信息包含订单号、型号、数量和状态,其中状态值为1表示确认订单,-1表示取消订单。工作人员首先挑选出确认的订单,然后对着订单按花瓶型号进行分类统计,最后交给生产部门生产。订单信息存储在“orders.csv”文件中,文件的数据格式如图1所示。请回答下列问题:
(1)若某天的订单如图2所示,则当天应生产的B型号花瓶数量为__________个。
订单号 型号 数量 状态
S001 A 1000 1
S002 B 2000 1
S003 B 1500 -1
S004 C 900 1
S005 B 800 1
S006 C 700 1
S007 A 500 -1
S008 B 600 1
图1 
图2 
3400
(2)定义如下readdata()函数,函数功能是从订单文件中挑选出确认的订单,并将订单的订单号、型号和数量存储在列表orders中,程序画线处应填入的代码为__________。
def readdata():
  import csv
  f=open("orders.csv","r",encoding="utf-8")
  f_csv=csv.reader(f)
  title=next(f_csv) #读取标题行
  for line in f_csv:        #逐行读取数据
    if line[3]=="1":
      orders.append([line[0], ▲ ,int(line[2])])
  return orders
  f.close()
line[1]
(3)实现按花瓶型号分类统计花瓶数量的Python程序如下,程序运行结果如图3所示。请在画线处填入合适的代码。
当天订单信息为: [[ s001 , B ,6000], [ s002 , A ,9000], [ s003 , C",7000], [ s005°, A ,62001,I s006 , B ,3000], [ s007 , C ,9500],[ s008 , A ,5000]] 分类订单统计结果为:
[ s002 , A ,9000]→[ s005 , A ,6200]→
[ s008 , A ,5000]→共计20200个
[ s001, B ,6000]->[ s006°, B ,3000]->共计9000个
[ s003 , c,7000]→[ s007 , c ,9500]→共计16500个
图3
orders=[] #存储订单信息
readdata()
print("当天订单信息为:\n",orders)
n=len(orders);m=3
tlist=[] #以链表形式存储相同型号花瓶首尾订单的索引值
for i in range(n):
  orders[i].append(-1)  #orders[i]追加一个元素-1
for i in range(m):
  tlist.append([-1,-1])  #tlist追加一个元素[-1,-1]
i=0
while i  k=ord(orders[i][1])-ord("A")
  if tlist[k][0]==-1:
    tlist[k][0]=i
  else:
    p=tlist[k][1]
    ①_________________
  tlist[k][1]=i
  i+=1
p=0
orders[p][3]=i
print("分类订单统计结果为:")
while p  y=tlist[p][0]
  total=0
  while y!=-1:
    print(orders[y][0:3],"->",end="")
    ②___________________________________________
    y=orders[y][3]
  print("共计",total,"个")
  ③____________________
total=total+orders[y][2]或total+=orders[y][2]
p=p+1或p+=1
【解析】 本题考查链表知识。(1)当天应生产的B型号花瓶数量为2000+800+600,共3400个。(2)readdata()函数的功能是过滤撤销的订单,根据第4列的订单状态,从文件中读取的前3列的数据,因此划线处代码为line[1]。(3)本题的算法思想是:首先根据订单中的花瓶型号构建三张链表(tlist[0]、tlist[1]和tlist[2]),分别存储不同型号花瓶的订单信息,链表tlist只记录首尾两张订单的索引号,中间的订单信息则记录在orders表示的链表中。要在链表中增加一个节点,可以通过tlist[i][1]直接找到链表尾节点,然后接在后面 ,并且更新tlist[i][1]作为新的链表尾节点,因此①处代码为orders[p][3]=i。然后统计每张链表中的花瓶数量,统计时,首先获取当前链表中第一张订单的索引号,然后按照链表顺序将各订单的花瓶数量累加,从而求出各种型号花瓶的总数量, 因此②处代码为total=total+orders[y][2],接着对存储另外型号花瓶的链表进行处理,因此③处代码为p=p+1或p+=1。二、 链表及其基本操作
1. 使用链表结构模拟某校浏览路线,链表a中每一个节点包含三个数据,第1个为地点名称,第2个为预计停留时间(单位:分钟),第3个为指向下一个地点的指针。可以从多个地点开始浏览,但只能从“南大门”离开,输出显示从各景点进入路线及预计总时间的代码如下。
a=[["校训石",15,2],["教学楼",30,2],["风雨操场",25,5],["科技楼",40,4],["新华书店",60,5],["南大门",20,-1]]
head=[0,1,3]
for i in range(len(head)):
     (1)   
  s=a[p][1]
  while a[p][2]!=-1:
    print(a[p][0],end="→")
       (2)  
       (3)  
  print(a[p][0])
  print("预计时间:",s,"分钟")
上述程序画线处的可选代码有:
①p=head ②p=head[i] ③s=s+a[p][1] ④p=a[p][2]
则(1)、(2)、(3)处代码依次为( D )
A.①③④ B.①④③
C.②③④ D.②④③
【解析】 本题考查链表节点遍历知识。由代码可知,p为当前节点,且起始节点可选,因此(1)处代码应该是p=head[i],从而排除选项A和B。代码(2)和(3)处,由于s的初值已经包含当前节点的访问时间(s=a[p][1])但却没有输出当前节点的地点名称,因此应该先指向下一个节点,然后再将该节点的访问时间累加到s中,即先④再③,故选D。
2. 使用列表d模拟链表结构(节点数大于0),每个节点包含数据区域和指针区域,h为头指针。下列程序段实现了删除数据区域为奇数的节点。
q=p=h=2
while p!=-1:
  if d[h][0]%2==1:
     (1)  
   q=p=h
  elif d[p][0]%2==1:
     (2)  
   p=d[p][1]
  else:
    q=p
    p=d[p][1]
画线处可选代码如下:
①h=d[h][1] ②p=d[p][1] ③d[p][1]=d[q][1] 
④d[q][1]=d[p][1]
下列选项中,代码顺序正确的是( C )
A.①③ B.②③
C. ①④ D.②④
【解析】 本题考查链表节点删除知识。由代码可知,p为当前节点,q为p的前驱节点,删除当前节点p的代码应该是d[q][1]=d[p][1],因此可以排除③,即选项AB不可能。h为头节点,需要单独考虑,若头节点为奇数则删除头结点h,且修改头节点的值,因此(1)处代码为h=d[h][1],故本题选C。
3. 用链表实现数组的升序排序,Python程序如下,方框中应填入的正确代码是( A )
#生成无序数组,元素如[3,-1],分别表示数值和指针(指针初值均为-1),代码略
head=0
for i in range(1,len(a)):
  q=head
  p=a[head][1]
  if a[head][0]>a[i][0]:
    a[i][1]=head
    head=i
  else:
          
    a[q][1]=i ; a[i][1]=p
A. while p!=-1 and a[p][0]  q=p
  p=a[p][1]
B. while p!=-1 and a[p][0]  p=a[p][1]
  q=p
C. while p!=-1 and a[q][0]  p=q
  q=a[q][1]
D. while q!=-1 or a[p][0]  q=p
  p=a[p][1]
【解析】 本题考查链表与排序的综合应用。该算法中head固定在位置0,每轮均需要在已完成排序的链表中遍历,并把a[i]插入到q和p之间。本轮查找时,若p节点数据小于a[i]并且未到链表尽头(p不等于-1),则继续搜索,然后更新前置节点q和后继节点p。A正确。
4. 使用列表d模拟链表结构(节点数大于0),每个节点包含数据区域和指针区域,head为头指针。现要删除链表中数据值在[begin,end]范围的节点,实现该功能的部分程序段如下,方框中应填入的代码是( A )
d=[[4, 5], [10, 2], [12, 4], [1, 0], [16, -1], [7, 1]]
head=3
q=head;p=head
while p!=-1:
  if d[p][0]end:
    q=p
    p=d[p][1]
else:
A. if head!=p:
  d[q][1]=d[p][1]
else:
  head=d[p][1]
p=d[p][1]
B. if head==p:
  d[q][1]=d[p][1]
else:
  head=d[p][1]
p=d[p][1]
C. if head!=p:
  p=d[p][1]
else:
  head=d[p][1]
p=d[p][1]
D. if head==p:
  p=d[p][1]
else:
  head=d[p][1]
  p=d[p][1]
【解析】 本题考查链表节点删除的知识。根据代码可知,p为当前节点,q为p的前驱节点。其删除数据节点的逻辑为:若数值不在[begin,end]范围之内的节点p,依次往后进行迭代。若数值在[begin,end]范围之内的节点p,将当前节点删除。删除节点p时又可分为两种情况,若删除的是头节点,需要更新head值为当前节点p的下一个节点,代码为head=d[p][1]。若删除的节点不是头节点,则让p的前驱节点q直接指向p的后继节点,即可实现删除p节点,因此其代码是d[q][1]=d[p][1]。A正确。
5. 使用列表d模拟链表结构(节点数大于2,且不存在连续为0的节点),每个节点包含数据区域和指针区域,h为头指针。链表的开头和末尾的节点数据区域的值均为0,如图1所示。现要把相邻两个数值为0的节点之间所有节点合并为一个节点,该节点值为所有合并节点值之和,并将值为0的节点移除,结果如图2所示。实现该功能的部分程序段如下,方框中应填入的正确代码是( B )
图1   图2
k=h;p=d[k][1]
while k!=-1 and p!=-1:
       
  p=d[k][1]
A. if d[p][0]!=0:
  d[k][0]+=d[p][0]
d[k][1]=d[p][1]
if d[p][0]==0:
  k=p
B. if d[p][0]!=0:
  d[k][0]+=d[p][0]
d[k][1]=d[p][1]
if d[p][0]==0:
  k=d[k][1]
C. if d[p][0]==0:
    k=p
else:
  d[k][0]+=d[p][0]
  d[k][1]=d[p][1]
D. if d[p][0]==0:
  k=d[k][1]
else:
  d[k][0]+=d[p][0]
  d[k][1]=d[p][1]
【解析】 本题考查链表操作等相关知识。题干明确告知头节点和尾节点数据区域均为0,因此从第一个节点开始就需要将后继的值加入当前头节点的数据域中,并删除值已经被加入的节点。而当下一次遇到数值为0的节点时,就需要思考,最后一个节点也是数据为0的节点,如果按照如上的方案进行后几个0节点的操作,那么最后一个0节点将无法被删除。因此,当跳过第一个0节点以后,当遇到下一个0数据域的节点时,直接跳过当前节点,以0数据域的下一个节点作为当前 k的节点,既保证了数据域的不丢失,也保证了删除数据域为 0 的节点。A选项,当碰到数据域的0节点时,k移动到当前0节点数据域,但是当前的节点在上一次的使用中已经被删除,A错误。当碰到数据域的0节点时,k 移动到当前0节点数据域,最后一个0节点无法被删除,C、D错误。
6. 使用列表d模拟链表结构(节点数大于1),每个节点包含数据区域(数据均为整型,范围为0~9)和指针区域,h为头指针,如图1所示。现要对该链表节点进行去重操作,只保留最后一次出现的节点,结果如图2所示。实现该功能的程序段如下,方框中应填入的代码是( B )
图1   图2
lst = [0]*10
p = h
while p != -1:
  lst[d[p][0]] += 1
  p = d[p][1]
q, p = h, h
while d[p][1] != -1:
         
  p = d[p][1]
A. if lst[d[p][0]] >= 2:
 if p == h:
   h = d[h][1]
 else:
   d[q][1] = d[p][1]
   lst[d[p][0]] -= 1
else:
   q = p
B. if lst[d[p][0]] < 2:
 q = p
elif p == h:
  lst[d[p][0]] -= 1
  h = d[h][1]
else: 
  lst[d[p][0]] -= 1
  d[q][1] = d[p][1]
C. if lst[d[p][0]] >= 2:
 if p == h:
   h = d[h][1]
 else:
   d[d[p][1]][1] = q
   lst[d[p][0]] -= 1
else:
   q = d[q][1]
D. if lst[d[p][0]] < 2:
  q = d[p][1]
else:
  if p != h: 
    d[q][1] = p
  else:
    h = d[h][1]
  lst[d[p][0]] -= 1
【解析】 本题考查链表的综合应用。删除链表的重复元素,先通过遍历将链表元素按数值放入 lst 数组中,lst 数组实现统计每个元素出现的次数。若次数小于 2 ,则保留,若大于或等于2,则通过链表元素删除,保留最后一次出现的节点。删除链表节点分为两种情况:①删除头节点,通过修改头指针为 h=d[h][1]实现;②删除非头指针,q 为前驱节点,p 为当前节点,通过修改前驱节点指针域d[q][1]=d[p][1],删除当前 p 指向的节点。B正确。
7. 有如下Python程序段:
a=[[1,1],[2,2],[3,3],[4,-1]]
head=0
cur=a[head][1]
a[head][1]=-1
while cur!=-1:
  next=a[cur][1]
  a[cur][1]=head
  head,cur=cur,next
则程序执行后,a的值为( B )
A.[[1,1],[2,2],[3,3],[4,-1]] B.[[1,-1],[2,0],[3,1],[4,2]]
C.[[4,1],[3,2],[2,3],[1,-1]] D.[[4,-1],[3,0],[2,1],[1,2]]
【解析】 本题考查链表操作知识。该程序通过修改各个节点的指针值,来实现链表全部节点逆转的功能。程序运行结束后head的值为3,结果如选项B。
8. 使用列表L模拟链表结构,每个节点包含数据区域和指针区域,现要删除该链表中的某一元素,示例输出结果如图所示,实现该功能的程序段如下,画线处应填入的代码依次是( C )
请输入要删除的数据:9
找到删除数据
7->4->8->6->5
>>>
==============RESTA
==
请输入要删除的数据:18
未找到删除数据
9->7->4->8->6->5
>>>
def delete(data,p):
  head=0
  if p==data[head][0]:
    head=data[head][1]
    print("找到删除数据")
  else:
    cur=pre=head
    while   (1)  :
      pre=cur
      cur=data[cur][1]
    if cur!=-1:
        (2)  
      print("找到删除数据")
    else:
      print("未找到删除数据")
    return head
L=[[9,3],[4,2],[8,4],[7,1],[6,5],[5,-1]]
key=int(input("请输入要删除的数据:"))
head=delete(L,key)
#输出删除后的结果程序省略
①data[cur][0]!=p and data[cur][1]!=-1
②data[cur][0]!=p and cur!=-1
③data[pre][1]=data[cur][1]
④data[cur][1]=data[pre][1]
A. ①③ B. ①④
C. ②③ D. ②④
【解析】 本题考查链表的基础操作知识。(1)处要完成的功能是,若当前节点cur的值不等于要删除的数p,且当前节点不是尾节点时,依次往下遍历,实现过程是迭代,即先将当前节点cur赋值给前驱节点pre,然后cur继续往下走一步,因此在①②代码中,②的表达式正确。(2)处实现的功能是,若找到需要删除的数据,且该节点不是尾节点时删除当前节点。分析代码可知,cur是当前节点,而pre是cur的前驱节点,因此删除的数据的正确代码是前驱节点pre直接指向当前节点cur的后继节点data[cur][1],即data[pre][1]=data[cur][1],因此在③④中选择③。C正确。
9. 给定一个链表a,以表头元素为基准数,将小于基准的节点移动到它的左侧,且保持节点相对顺序不变;大于基准的节点保持不动。如图1所示的链表处理后的结果如图2所示。实现该功能的程序段如下,head为头指针,则方框中应填入的代码是( D )
图1   图2
pivot = a[head][0]
p, r = head, -1
while a[p][1] != -1:
  q = a[p][1]
  if a[q][0] < pivot:
    a[p][1] = a[q][1]
            
    r = q
  else:
    p = a[p][1]
A. if r == -1:
 a[q][1]=p
 head=q
else:
 a[r][1]=a[q][1]
 a[q][1]=r
B. if r == -1:
 a[p][1]=q
 head=q
else:
 a[r][1]=a[p][1]
 a[q][1]=r
C. if r == -1:
 a[p][1]=q
 head=q
else:
 a[q][1]=a[r][1]
 a[r][1]=q
D. if r == -1:
 a[q][1]=head
 head=q
else:
 a[q][1]=a[r][1]
 a[r][1]=q
【解析】 本题考查链表知识。第5行元素值的比较可以看出,q节点表示当前待移动的节点,p节点是它的前一个节点。第6行相当于让q的前一个节点指向q的后一个节点,即跳过了q节点。第8行程序让r指向q节点,而q是最后一次移动的节点,因此r可以看成左侧链表的尾节点。第10行是q节点的值大于等于基准的情况,这时p直接往后移一位,那么p就是基准右侧链表的最后一个节点。对于四个选项的条件都是r为-1的情况,即r还未指向任何一个节点,也相当于左侧链表为空的情况。这时可以让q节点的下一个节点指向右侧节点的第一个节点,即p或者head节点(如选项A和D所示)。当r指向一个实际元素时,新元素应该如何插入 放在r的前面还是r的后面 这也是选项A和选项D中“else”分支语句的差别。考虑到题目中要求元素移动后保持相对顺序不变,后插入的元素应该在前插入的元素后面,因此元素应该插在r的后面。选项A将q节点插在了r的前面。选项D将q节点插在了r的后面,D正确。选项B和C,在if分支中的逻辑与第6行程序有冲突。
10. 有如下Python程序段:
a=[[1,3],[1,0],[7,1],[4,5],[1,-1],[6,4]]
x=1
p=head=2
if x==a[p][0]:
  head=a[p][1]
else:
  while p!=-1:
    if x==a[p][0]:
      a[pre][1]=a[p][1]
    else:
      pre=p
    p=a[p][1]
运行该段程序后,a[2][1]的值为( D )
A. -1 B. 0
C. 1 D. 3
【解析】 本题考查链表的遍历及删除节点操作。阅读代码可知,选择结构部分的操作为:当x为当前链表头指针所指的节点的数据,那就删除头节点,如果不是就遍历后续节点并删除数据域为1的节点。因为删除需要记录当前节点的前驱节点,使用pre来存储。原链表为7→1→1→4→6→1。故删除了数据域为1的节点之后,数据7直接指向了数据4,故a[2][1]为3,D正确。
11. 使用列表d模拟链表结构(节点数大于1),每个节点包含起始数值、连续长度、指针区域,h为头指针。链表中各节点已按起始数值由小到大排列,各个节点表示的数值区间不重叠,例如链表d为[[20, 100, 3], [150, 50, 2], [250, 60, -1], [120, 30, 1]],h=0,其中节点 [20, 100, 3]表示从数值20开始有长度为100的连续值(20到119),3代表后继节点索引为3,现要合并链表各节点连续的数值区间,合并后链表d的数据修改为[[20, 180,2], [150, 50, 2], [250, 60, -1], [120, 30, 1]],h=0。实现该功能的Python程序段如下,加框处的代码依次是( B )
q=h=0
p=d[q][2]
while p!=-1:
  if d[p][0]==d[q][0]+d[q][1]:
    d[q][1]=d[q][1]+d[p][1]
  else:
     (1) 
   (2) 
   (3) 
上述程序中方框处可选语句如下:
①q=p ②d[q][2]=p ③p=d[p][2]
A. ①、②、③ B. ①、③、②
C. ②、①、③ D. ②、③、①
【解析】 本题考查链表的基础知识。分析代码可得,p是当前节点,q是p的前驱节点。如果q、p指向链表相邻两个节点的数值区间连续,则将两个节点进行合并,更新q节点的连续长度(即q节点的连续数值长度加上p节点的连续数值长度)。同时q节点的指针域需要指向当前p节点的后继节点。否则,将指针q的值更新为p,指针p后移指向下一节点。B正确。
12. 链表a中各节点由数据域和指针构成,并按数据域数值升序排列(头节点数据为奇数),现要修改各节点顺序,按奇数在前升序、偶数在后升序的顺序排列,如图所示。实现该功能的程序段如下,方框中应填入的代码是( B )
a = [[8,1],[9,-1],[6,0],[1,5],[5,2],[2,4]]
p = t = head = 3
while a[t][1] != -1:
  k = a[t][1]
  if a[k][0] % 2 == 1:
            
  else:
    t = a[t][1]
A. a[t][1] = a[p][1]
a[p][1] = t
p = t
t = k
B. a[t][1] = a[k][1]
a[k][1] = a[p][1]
a[p][1] = k
p = a[p][1]
C. a[p][1] = t
a[t][1] = a[p][1]
p = a[p][1]
t = k
D. t = a[t][1]
a[k][1] = a[p][1]
a[p][1] = k
p = k
【解析】 本题考查链表操作。本题的重点是理解几个指针的作用:p,t从头节点(奇数)出发,k为t的后继,若a[k][0]为偶数,则t指针后移……直到a[k][0]为奇数时才停止,此时t为连续偶数的最后一个,接下来从原位置删除k点(a[t][1]=a[k][1])。将k点连接到p之后:a[k][1]=a[p][1];a[p][1]=k。p指针后移,保留奇数段的链尾:p=a[p][1]。B正确。
13. 利用链表实现升序排序:二维列表a同时保存数据域和指针域,排序的过程就是将每个数据的指针域不断链接到已有的有序链表的合适位置,直到所有的数据均链接到链表中。
例如,将某节点插入到已有链表中,根据大小比较有三种情况:插入到最前面、插入到最后、插入到中间。具体程序设计方法如下:
①将待排序的n个数保存在列表a中,且指针域的值均为-1,形成n个没有链接的节点。
②将每个节点看成只含有一个节点的链表head,且head=0。
③将第i个节点插入到链表head的适当位置,使head仍有序,此时head成为含有两个节点的有序链表;以此方法依次将a列表中的其他节点插入到链表head中,最后链表head上包含所有节点,且节点有序。依次输出head链表的数据域即可完成排序。
程序运行界面如图所示,采用此思想进行升序排序的Python代码如下,请回答下列问题:
原始链表为:[[43,-1],[68,-1],[25,-1],[17,-1],[52,-1]]
排序后链表:[[43,4],[68, -1],[25,0],[17,2],[52,1]]
排序后数据:17 25 43 52 68
#随机生成列表a的数据域的值,且指针域全部为-1,代码略
n = len(a)
print("原始链表为:",a)
head=0
for i in range(1,n):
 ① k=head 
 if a[k][0]>=a[i][0]:
   a[i][1]=k
   head=i
 else:
   while a[i][0] > a[a[k][1]][0]:  #改错
     k = a[k][1]
   a[i][1] = a[k][1]
   ② a[k][1]=i 
print("排序后链表:",a)
print("排序后数据:",end=" ")
k=head
while k != -1:
  print(a[k][0],end=" ")
 ③ k=a[k][1] 
(1)若用该算法进行升序排序,a=[[46, -1], [19, -1], [10, -1], [37, -1]],排序完成后,head变量的值为 2 。
(2)为实现上述功能,请在画线处填入合适的代码。
(3)加框处代码有错误,请改正。
【答案】 a[i][0]> a[a[k][1]][0]and a[k][1]!=-1
【解析】 本题考查链式存储的插入排序算法。(1)链表是通过head进行遍历数据,升序排序时,最小值下标为2,故head值为2。(2)①此处表示插入的节点位于最前面的情况,故答案是k=head,为了避免head的值发生改变,因此使用k模拟head指针。②此处寻找插入位置,若插入数据a[i][0]大于当前值,则找下一个节点,直到到达链表的最后一个节点,若找到位置,则先更新i的下一个为k的下一个,再更新k的下一个为i节点(顺序不可更改)。③此处通过k(相当于head)遍历整个链表,并输出数据域,下一个节点的位置是k=a[k][1]。(3)否则继续循环每个节点,将节点i和当前遍历节点k的下一个节点进行比较,所以找到的k为第一个大于i的节点的前一个节点。除了考虑比较大小外,还必须考虑a[k][1]的值不能为-1(-1表示尾部)。
14. 某花瓶厂有三台不同型号的机器,可生产ABC三种不同型号的花瓶。厂家每天会收到很多网上订单,每个客户的订单信息包含订单号、型号、数量和状态,其中状态值为1表示确认订单,-1表示取消订单。工作人员首先挑选出确认的订单,然后对着订单按花瓶型号进行分类统计,最后交给生产部门生产。订单信息存储在“orders.csv”文件中,文件的数据格式如图1所示。请回答下列问题:
(1)若某天的订单如图2所示,则当天应生产的B型号花瓶数量为 3400 个。
图1 
订单号 型号 数量 状态
S001 A 1000 1
S002 B 2000 1
S003 B 1500 -1
S004 C 900 1
S005 B 800 1
S006 C 700 1
S007 A 500 -1
S008 B 600 1
图2
(2)定义如下readdata()函数,函数功能是从订单文件中挑选出确认的订单,并将订单的订单号、型号和数量存储在列表orders中,程序画线处应填入的代码为
 line[1] 。
def readdata():
  import csv
  f=open("orders.csv","r",encoding="utf-8")
  f_csv=csv.reader(f)
  title=next(f_csv) #读取标题行
  for line in f_csv:        #逐行读取数据
    if line[3]=="1":
      orders.append([line[0],   ▲  ,int(line[2])])
  return orders
  f.close()
(3)实现按花瓶型号分类统计花瓶数量的Python程序如下,程序运行结果如图3所示。请在画线处填入合适的代码。
当天订单信息为: [[ s001 , B ,6000],[ s002 , A ,9000],[ s003 , C",7000],[ s005°, A ,62001,I s006 , B ,3000],[ s007 , C ,9500],[ s008 , A ,5000]] 分类订单统计结果为: [ s002 , A ,9000]→[ s005 , A ,6200]→[ s008 , A ,5000]→共计20200个 [ s001, B ,6000]->[ s006°, B ,3000]->共计9000个 [ s003 , c,7000]→[ s007 , c ,9500]→共计16500个
图3
orders=[] #存储订单信息
readdata()
print("当天订单信息为:\n",orders)
n=len(orders);m=3
tlist=[] #以链表形式存储相同型号花瓶首尾订单的索引值
for i in range(n):
  orders[i].append(-1)  #orders[i]追加一个元素-1
for i in range(m):
  tlist.append([-1,-1])  #tlist追加一个元素[-1,-1]
i=0
while i  k=ord(orders[i][1])-ord("A")
  if tlist[k][0]==-1:
    tlist[k][0]=i
  else:
    p=tlist[k][1]
    ① orders[p][3]=i 
  tlist[k][1]=i
  i+=1
p=0
print("分类订单统计结果为:")
while p  y=tlist[p][0]
  total=0
  while y!=-1:
    print(orders[y][0:3],"->",end="")
    ② total=total+orders[y][2]或total+=orders[y][2] 
    y=orders[y][3]
  print("共计",total,"个")
  ③ p=p+1或p+=1 
【解析】 本题考查链表知识。(1)当天应生产的B型号花瓶数量为2000+800+600,共3400个。(2)readdata()函数的功能是过滤撤销的订单,根据第4列的订单状态,从文件中读取的前3列的数据,因此划线处代码为line[1]。(3)本题的算法思想是:首先根据订单中的花瓶型号构建三张链表(tlist[0]、tlist[1]和tlist[2]),分别存储不同型号花瓶的订单信息,链表tlist只记录首尾两张订单的索引号,中间的订单信息则记录在orders表示的链表中。要在链表中增加一个节点,可以通过tlist[i][1]直接找到链表尾节点,然后接在后面 ,并且更新tlist[i][1]作为新的链表尾节点,因此①处代码为orders[p][3]=i。然后统计每张链表中的花瓶数量,统计时,首先获取当前链表中第一张订单的索引号,然后按照链表顺序将各订单的花瓶数量累加,从而求出各种型号花瓶的总数量, 因此②处代码为total=total+orders[y][2],接着对存储另外型号花瓶的链表进行处理,因此③处代码为p=p+1或p+=1。

展开更多......

收起↑

资源列表