第2章线性表答案Word文档格式.docx
《第2章线性表答案Word文档格式.docx》由会员分享,可在线阅读,更多相关《第2章线性表答案Word文档格式.docx(49页珍藏版)》请在冰豆网上搜索。
next=px->
next;
px->
next=py
4.n-i+1
5.主要是使插入和删除等操作统一,在第一个元素之前插入元素和删除第一个结点不必另作判断。
另外,不论链表是否为空,链表指针不变。
6.O
(1),O(n)7.单链表,多重链表,(动态)链表,静态链表
8.f->
next=p->
f->
prior=p;
p->
next->
prior=f;
next=f;
9.p^.priors^.prior^.next
10.指针11.物理上相邻指针12.42
13.从任一结点出发都可访问到链表中每一个元素。
14.u=p->
next=u->
free(u);
15.L->
next==L16.p->
next!
=null
17.L->
next==L&
&
L->
prior==L18.s->
p->
next=s;
19.
(1)IFpa=NILTHENreturn(true);
(2)pb<
>
NILANDpa^.data>
=pb^.data
(3)return(inclusion(pa,pb));
(4)pb:
=pb^.next;
(5)return(false);
非递归算法:
(1)pre:
=pb;
(2)pa<
NILANDpb<
NILANDpb^.data>
=pa^.data(3)pa:
=pa^.next;
pb:
=pb->
(4)pb:
=pre^.next;
pre:
pa:
(5)IFpa=NILTHENreturn(true)ELSEreturn(false);
[注]:
本题是在链表上求模式匹配问题。
非递归算法中用指针pre指向主串中开始结点(初始时为第一元素结点)。
若主串与子串对应数据相等,两串工作指针pa和pb后移;
否则,主串工作指针从pre的下一结点开始(这时pre又指向新的开始结点),子串工作指针从子串第一元素开始,比较一直继续到循环条件失败。
若pa为空,则匹配成功,返回true,否则,返回false。
20.A.VARhead:
ptrB.new(p)C.p^.data:
=kD.q^.next:
=pE.q:
=p(带头结点)
21.
(1)new(h);
∥生成头结点,以便于操作。
(2)r^.next:
=p;
(3)r^.next:
=q;
(4)IF(q=NIL)THENr^.next:
22.A:
r^.link^.data<
maxANDq^.link^.data<
max
B:
r:
=r^.linkC:
q^.linkD:
q^.linkE:
r^.linkF:
r^.link
G:
=s(或r:
=r^.link)H:
=r^.linkI:
q^.link:
=s^.link
23.
(1)la
(2)0(3)j<
i-1(4)p↑.next(5)i<
1
24.
(1)head^.left:
=s∥head的前驱指针指向插入结点
(2)j:
=1;
(3)p:
=p^.right∥工作指针后移
(4)s^.left:
=p
(5)p^.right^.left:
=s;
∥p后继的前驱是s
(6)s^.left:
25.
(1)i<
=L.last∥L.last为元素个数
(2)j:
=j+1∥有值不相等的元素
(3)L.elem[j]:
=L.elem[i]∥元素前移
(4)L.last:
=j∥元素个数
26.(A)p^.link:
∥拉上链,前驱指向后继
(B)p:
∥新的前驱
(C)p^.link:
=head;
∥形成循环链表
(D)j:
=0;
∥计数器,记被删结点
(E)q:
=p^.link∥记下被删结点
(F)p^.link=q^.link∥删除结点
27.
(1)p:
=r;
∥r指向工作指针s的前驱,p指向最小值的前驱。
(2)q:
∥q指向最小值结点,s是工作指针
(3)s:
=s^.link∥工作指针后移
(4)head:
=head^.next;
∥第一个结点值最小;
(5)p^link:
=q^.link;
∥跨过被删结点(即删除一结点)
28.
(1)l^.key:
=x;
∥头结点l这时起监视哨作用
(2)l^.freq:
=p^.freq∥头结点起监视哨作用
(3)q->
pre->
next=q->
q->
pre=q->
pre;
∥先将q结点从链表上摘下
q^.next:
q^.pre:
=p^.pre;
p^.pre->
next:
p^.pre:
∥结点q插入结点p前
(4)q^.freq=0∥链表中无值为x的结点,将新建结点插入到链表最后(头结点前)。
29.
(1)a^.key:
=’@’∥a的头结点用作监视哨,取不同于a链表中其它数据域的值
(2)b^.key:
=p^.key∥b的头结点起监视哨作用
(3)p:
=p^.next∥找到a,b表中共同字母,a表指针后移
(4)0(m*n)
30.C部分:
(1)p!
=null∥链表未到尾就一直作
(2)q∥将当前结点作为头结点后的第一元素结点插入
31.
(1)L=L->
∥暂存后继
(2)q=L;
∥待逆置结点
(3)L=p;
∥头指针仍为L
32.
(1)p^.next<
p0
(2)r:
=p^.next(3)p^.next:
=q0;
(4)q0:
=p;
(5)p:
=r
33.
(1)r
(2)NIL(3)x<
head^.data(4)p^.data<
x
(5)p:
=p^.next(6)p^.data>
(7)r(8)p
(9)r(10)NIL(11)NIL
34.
(1)pa!
=ha∥或pa->
exp!
=-1
(2)pa->
exp==0∥若指数为0,即本项为常数项
(3)q->
next=pa->
next∥删常数项
(4)q->
next∥取下一元素
(5)=pa->
coef*pa->
exp
(6)--∥指数项减1
(7)pa∥前驱后移,或q->
next
(8)pa->
next∥取下一元素
35.
(1)q:
∥q是工作指针p的前驱
(2)p^.data>
m∥p是工作指针
(3)r:
∥r记最大值的前驱,
(4)q:
∥或q:
=q^.next;
(5)r^.next:
∥或r^.next:
=r^.next^.next删最大值结点
36.
(1)L->
next=null∥置空链表,然后将原链表结点逐个插入到有序表中
(2)p!
=null∥当链表尚未到尾,p为工作指针
(3)q!
=null∥查p结点在链表中的插入位置,这时q是工作指针。
(4)p->
next=r->
next∥将p结点链入链表中
(5)r->
next=p∥r是q的前驱,u是下个待插入结点的指针。
37.程序(a)PASCAL部分(编者略)
程序(b)C部分
(1)(A!
=null&
B!
=null)∥两均未空时循环
(2)A->
element==B->
element∥两表中相等元素不作结果元素
(3)B=B->
link∥向后移动B表指针
(4)A!
=null∥将A表剩余部分放入结果表中
(5)last->
link=null∥置链表尾
四、应用题
1.
(1)选链式存储结构。
它可动态申请内存空间,不受表长度(即表中元素个数)的影响,插入、删
除时间复杂度为O
(1)。
(2)选顺序存储结构。
顺序表可以随机存取,时间复杂度为O
(1)。
2.链式存储结构一般说克服了顺序存储结构的三个弱点。
首先,插入、删除不需移动元素,只修改指针,时间复杂度为O
(1);
其次,不需要预先分配空间,可根据需要动态申请空间;
其三,表容量只受可用内存空间的限制。
其缺点是因为指针增加了空间开销,当空间不允许时,就不能克服顺序存储的缺点。
3.采用链式存储结构,它根据实际需要申请内存空间,而当不需要时又可将不用结点空间返还给系统。
在链式存储结构中插入和删除操作不需要移动元素。
4.线性表栈队列串顺序存储结构和链式存储结构。
顺序存储结构的定义是:
CONSTmaxlen=线性表可能达到的最大长度;
TYPEsqlisttp=RECORD
elem:
ARRAY[1..maxlen]OFElemType;
last:
0..maxlen;
END;
链式存储结构的定义是:
TYPEpointer=↑nodetype;
nodetype=RECORD
data:
ElemType;
next:
pointer;
linklisttp=pointer;
5.顺序映射时,ai与ai+1的物理位置相邻;
链表表示时ai与ai+1的物理位置不要求相邻。
6.在线性表的链式存储结构中,头指针指链表的指针,若链表有头结点则是链表的头结点的指针,头指针具有标识作用,故常用头指针冠以链表的名字。
头结点是为了操作的统一、方便而设立的,放在第一元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等),有头结点后,对在第一元素结点前插入结点和删除第一结点,其操作与对其它结点的操作统一了。
而且无论链表是否为空,头指针均不为空。
首元结点也就是第一元素结点,它是头结点后边的第一个结点。
7.见上题6。
8.
(1)将next域变为两个域:
pre和next,其值域均为0..maxsize。
初始化时,头结点(下标为0的元素)其next域值为1,其pre域值为n(设n是元素个数,且n<
maxsize)
(2)stalist[stalist[p].pre].pre;
(3)stalist[p].next;
9.在单链表中不能从当前结点(若当前结点不是第一结点)出发访问到任何一个结点,链表只能从头指针开始,访问到链表中每个结点。
在双链表中求前驱和后继都容易,从当前结点向前到第一结点,向后到最后结点,可以访问到任何一个结点。
10.本题是链表的逆置问题。
设该链表带头结点,将头结点摘下,并将其指针域置空。
然后从第一元素结点开始,直到最后一个结点为止,依次前插入头结点的后面,则实现了链表的逆置。
11.该算法的功能是判断链表L是否是非递减有序,若是则返回“true”;
否则返回“false“。
pre指向当前结点,p指向pre的后继。
12.q=p->
free(q);
13.设单链表的头结点的头指针为head,且pre=head;
while(pre->
=p)pre=pre->
s->
next=p;
pre->
14.设单链表带头结点,工作指针p初始化为p=H->
(1)while(p!
data!
=X)p=p->
if(p==null)return(null);
∥查找失败
elsereturn(p);
∥查找成功
(2)while(p!
data<
X)p=p->
if(p==null||p->
data>
X)return(null);
elsereturn(p);
(3)while(p!
X)p=p->
∥查找失败
elsereturn(p);
∥查找成功
15.本程序段功能是将pa和pb链表中的值相同的结点保留在pa链表中(pa中与pb中不同结点删除),pa是结果链表的头指针。
链表中结点值与从前逆序。
S1记结果链表中结点个数(即pa与pb中相等的元素个数)。
S2记原pa链表中删除的结点个数。
16.设q:
=p^.llink;
则
q^.rlink:
=p^.rlink;
p^.rlink^.llink:
p^.llink:
=q^.llink;
q^.llink^.rlink:
p^.rlink:
q^.llink:
17.
(1)前两个语句改为:
p.llink^.rlink<
-p^.rlink;
p^.rlink^.llink<
-p^.llink;
(2)后三个语句序列应改为:
q^.rlink<
∥以下三句的顺序不能变
-q;
p^.rlink<
18.mp是一个过程,其内嵌套有过程subp。
subp(s,q)的作用是构造从s到q的循环链表。
subp(pa,pb)调用结果是将pa到pb的前驱构造为循环链表。
subp(pb,pa)调用结果是将pb到pa的前驱(指在L链表中,并非刚构造的pa循环链表中)构造为循环链表。
总之,两次调用将L循环链表分解为两个。
第一个循环链表包含从pa到pb的前驱,L中除刚构造的pa到pb前驱外的结点形成第二个循环链表。
19.在指针p所指结点前插入结点s的语句如下:
s->
pre=p->
pre=s;
20.(A)f1<
NIL并且f2<
NIL
(B)f1↑.data<
f2↑.data
(C)f2↑.data<
f1↑.data
(D)f3↑.data<
(E)f1<
-f1↑.link或f2=f2↑.link;
21.1)本算法功能是将双向循环链表结点的数据域按值自小到大排序,成为非递减(可能包括数据域值相等的结点)有序双向循环链表。
2)
(1)r->
prior=q->
prior;
∥将q结点摘下,以便插入到适当位置。
(2)p->
prior=q;
∥
(2)(3)将q结点插入
(3)p->
next=q;
(4)r=r->
或r=q->
∥后移指针,再将新结点插入到适当位置。
五、算法设计题
1.[题目分析]因为两链表已按元素值递增次序排列,将其合并时,均从第一个结点起进行比较,将小的链入链表中,同时后移链表工作指针。
该问题要求结果链表按元素值递减次序排列。
故在合并的同时,将链表结点逆置。
LinkedListUnion(LinkedListla,lb)
∥la,lb分别是带头结点的两个单链表的头指针,链表中的元素值按递增序排列,本算法将两链表合并成一个按元素值递减次序排列的单链表。
{pa=la->
pb=lb->
∥pa,pb分别是链表la和lb的工作指针
la->
next=null;
∥la作结果链表的头指针,先将结果链表初始化为空。
while(pa!
pb!
=null)∥当两链表均不为空时作
if(pa->
data)
{r=pa->
∥将pa的后继结点暂存于r。
pa->
next=la->
∥将pa结点链于结果表中,同时逆置。
la->
next=pa;
pa=r;
∥恢复pa为当前待比较结点。
}
else
{r=pb->
∥将pb的后继结点暂存于r。
pb->
∥将pb结点链于结果表中,同时逆置。
next=pb;
pb=r;
∥恢复pb为当前待比较结点。
=null)∥将la表的剩余部分链入结果表,并逆置。
{r=pa->
pa=r;
}
while(pb!
=null)
{r=pb->
pb->
pb=r;
}∥算法Union结束。
[算法讨论]上面两链表均不为空的表达式也可简写为while(pa&
pb),两递增有序表合并成递减有序表时,上述算法是边合并边逆置。
也可先合并完,再作链表逆置。
后者不如前者优化。
算法中最后两个while语句,不可能执行两个,只能二者取一,即哪个表尚未到尾,就将其逆置到结果表中,即将剩余结点依次前插入到结果表的头结点后面。
与本题类似的其它题解答如下:
(1)[问题分析]与上题类似,不同之处在于:
一是链表无头结点,为处理方便,给加上头结点,处理结束再删除之;
二是数据相同的结点,不合并到结果链表中;
三是hb链表不能被破坏,即将hb的结点合并到结果链表时,要生成新结点。
LinkedListUnion(LinkedListha,hb)
∥ha和hb是两个无头结点的数据域值递增有序的单链表,本算法将hb中并不出现在ha中的数据合并到ha中,合并中不能破坏hb链表。
{LinkedListla;
la=(LinkedList)malloc(sizeof(LNode));
next=ha;
∥申请头结点,以便操作。
pa=ha;
∥pa是ha链表的工作指针
pb=hb;
∥pb是hb链表的工作指针
pre=la;
∥pre指向当前待合并结点的前驱。
while(pa&
pb)
data)∥处理ha中数据
{pre->
pre=pa;
pa=pa->
elseif(pa->
data)∥处理hb中数据。
{r=(LinkedList)malloc(sizeof(LNode));
∥申请空间
r->
data=pb->
data;
next=r;
pre=r;
∥将新结点链入结果链表。
pb=pb->
∥hb链表中工作指针后移。
else∥处理pa->
pre=pa;
pa=pa->
∥两结点数据相等时,只将ha的数据链入。
∥不要hb的相等数据
if(pa!
=null)pre->
∥将两链表中剩余部分链入结果链表。
elsepre->
free(la);
∥释放头结点.ha,hb指针未被破坏。
}∥算法nion结束。
(2)本题与上面两题类似,要求结果指针为lc,其核心语句段如下:
pa=la->
pb=hb->
lc=(LinkedList)malloc(sizeof(LNode));
pc=lc;
∥pc是结果链表中当前结点的前驱
while(pa&
{pc->
pc=pa;
else{pc->
pc=pb;
pb=pb->
if(pa)pc->
elsepc->
free(la);
free(lb);
∥释放原来两链表的头结点。
算法时间复杂度为O(m+n),其中m和n分别为链表la和lb的长度。
2.[题目分析]本组题有6个,本质上都是链表的合并操作,合并中有各种条件。
与前组题不同的是,叙述上是用线性表代表集合,而操作则是求集合的并、交、差(A∪B,A∩B,A-B)等。
本题与上面1.
(2)基本相同,不同之处1.
(2)中链表是“非递减有序”,(可能包含相等元素),本题是元素“递增有序”(不准有相同元素)。
因此两表中合并时,如有元素值相等元素,则应删掉一个。
LinkedListUnion(LinkedListha,hb)
∥线性表A和B代表两个集合,以链式存储结构存储,元素递增有序。
ha和hb分别是其链表的头指针。
本算法求A和B的并集A∪B,仍用线性表表示,结果链表元素也是递增有序。
{pa=ha->
∥设工作指针pa和pb。
pc=ha;
∥pc为结果链表当前结点的前驱指针。
else∥处理pa->
data.
u=pb;
free(u);
if(pa)pc->
∥若ha表未空,则链入结果表。
∥若hb表未空,则链入结果表。
free(hb);
∥释放hb头结点
return(ha);
与本题类似的其它几个题解答如下:
(1)解答完全同上2。
(2)本题是求交集,即只有同时出现在两集合中的元素才出现在结果表中。
其核心语句段如下:
pa=la->
pb=lb->
∥设工作指针pa和pb;
pc=la;
∥结果表中当前合并结点的前驱的指针。
pb)
data==pb->
data)∥交集并入结果表中。
{pc->
data){u=pa;
else{u=pb;
while(pa){u=pa;
}∥释放结点空间
while(pb){u=pb;
fre