数据结构习题集参考答案Word下载.docx
《数据结构习题集参考答案Word下载.docx》由会员分享,可在线阅读,更多相关《数据结构习题集参考答案Word下载.docx(64页珍藏版)》请在冰豆网上搜索。
![数据结构习题集参考答案Word下载.docx](https://file1.bdocx.com/fileroot1/2023-1/6/61bff9ad-5ed1-4f40-929f-773345b059bc/61bff9ad-5ed1-4f40-929f-773345b059bc1.gif)
typedefstruct
{intnum;
//学号
charname[8];
//姓名
floatscore;
/平均成绩
}node;
nodestudent[100];
3.第一层FOR循环判断n+1次,往下执行n次,第二层FOR执行次数为(n+(n-1)+(n-2)+…+1),第三层循环体受第一层循环和第二层循环的控制,其执行次数如下表:
i=123…n
j=nnnn…n
j=n-1n-1n-1n-1…
…………
j=333
j=222
j=11
执行次数为(1+2+…+n)+(2+3+…+n)+…+n=n*n(n+1)/2-n(n2-1)/6。
在n=5时,f(5)=55,执行过程中,输出结果为:
sum=15,sum=29,sum=41,sum=50,sum=55(每个sum=占一行,为节省篇幅,这里省去换行)。
4.解答:
(1)intlocate(dataytpeA[1..n],dateytpek)
{i=1;
while((i<
=n)&
&
(A[i]!
=k))i++;
if(i<
=n)return(i);
elsereturn(o);
}
最坏时间复杂度T(n)=O(n).
(2)VoidCZ_max(datatypeA[n],x,y)
{x=A[1];
y=A[1];
for(i=2;
i<
=n;
I++)
if(x<
A[i]{y=x;
x=A[i];
}/*替换最大值*/
elseif(y<
A[i]y=A[i];
/*替换次最大值*/
}
最坏情况时间复杂度T(n)=O(n).
第2章线性表
1.B
2.A
3.C
4.C
5..A
6.D
7.B
8.B
9.B
10.C
11.C
12.B
13.B
1.链表中的头结点仅起到标识的作用。
2.线性表采用链表存储时,结点和结点内部的存储空间可以是不连续的。
(√)
3.顺序存储方式插入和删除时效率太低,因此它不如链式存储方式好。
4.对任何数据结构链式存储结构一定优于顺序存储结构。
5.所谓静态链表就是一直不发生变化的链表。
6.线性表的特点是每个元素都有一个前驱和一个后继。
7.循环链表不是线性表.(×
8.线性表只能用顺序存储结构实现。
9.线性表就是顺序存储的表。
10.链表是采用链式存储结构的线性表,进行插入、删除操作时,在链表中比在顺序存储结构中效率高。
(√)
1.
必定
不一定
2.
头指针
头结点指针域
前驱结点指针域
3.双向链表
4.nO(n)n/2O(n)
5..单链表循环链表双向链表
6.指针
7.(n-1)/2
8.py->
next=px->
next;
px->
next=py
9.42
10.i=1;
i≤L.last
11.
(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是下个待插入结点的指针。
12.
(1)(A!
=null&
B!
=null)∥两均未空时循环
(2)A->
element==B->
element∥两表中相等元素不作结果元素
(3)B=B->
link∥向后移动B表指针
(4)A!
=null∥将A表剩余部分放入结果表中
(5)last->
link=null∥置链表尾
1.试述头结点,首元结点,头指针这三个概念的区别.
参考答案:
在线性表的链式存储结构中,头指针指链表的指针,若链表有头结点则是链表的头结点的指针,头指针具有标识作用,故常用头指针冠以链表的名字。
头结点是为了操作的统一、方便而设立的,放在第一元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等),有头结点后,对在第一元素结点前插入结点和删除第一结点,其操作与对其它结点的操作统一了。
而且无论链表是否为空,头指针均不为空。
首元结点也就是第一元素结点,它是头结点后边的第一个结点。
2.在单链表和双向链表中,能否从当前结点出发访问到任何一个结点?
在单链表中不能从当前结点(若当前结点不是第一结点)出发访问到任何一个结点,链表只能从头指针开始,访问到链表中每个结点。
在双链表中求前驱和后继都容易,从当前结点向前到第一结点,向后到最后结点,可以访问到任何一个结点。
3.一线性表存储在带头结点的双向循环链表中,L为头指针。
如下算法:
(1)说明该算法的功能。
(2)在空缺处填写相应的语句。
voidunknown(BNODETP*L)
{…
p=L->
q=p->
r=q->
next;
while(q!
=L)
{while(p!
=L)&
(p->
data>
q->
data)p=p->
prior;
prior->
next=r;
(1)______;
next=p->
prior=p;
(2)______;
(3)______;
q=r;
p=q->
(4)______;
}
1)本算法功能是将双向循环链表结点的数据域按值自小到大排序,成为非递减(可能包括数据域值相等的结点)有序双向循环链表。
2)
(1)r->
prior=q->
prior;
∥将q结点摘下,以便插入到适当位置。
(2)p->
next->
prior=q;
∥
(2)(3)将q结点插入
(3)p->
next=q;
(4)r=r->
或r=q->
∥后移指针,再将新结点插入到适当位置。
五、算法设计题
1.[题目分析]在递增有序的顺序表中插入一个元素x,首先应查找待插入元素的位置。
因顺序表元素递增有序,采用折半查找法比顺序查找效率要高。
查到插入位置后,从此位置直到线性表尾依次向后移动一个元素位置,之后将元素x插入即可。
voidInsert(ElemTypeA[],intsize,ElemTypex)
∥A是有size个元素空间目前仅有num(num<
size)个元素的线性表。
本算法将元素x插入到线性表中,并保持线性表的有序性。
{low=1;
high=num;
//题目要求下标从1开始
while(low<
=high)∥对分查找元素x的插入位置。
{mid=(low+high)/2;
if(A[mid]==x){low=mid+1;
break;
elseif(A[mid]>
x)high=mid-1;
elselow=mid+1;
for(i=num;
i>
=low;
i--)A[i+1]=A[i];
∥元素后移。
A[i+1]=x;
∥将元素x插入。
}算法结束。
[算法讨论]算法中当查找失败(即线性表中无元素x)时,变量low在变量high的右面(low=high+1)。
移动元素从low开始,直到num为止。
特别注意不能写成for(i=low;
=num;
i++)A[i+1]=A[i],这是一些学生容易犯的错误。
另外,题中未说明若表中已有值为x的元素时不再插入,故安排在A[mid]==x时,用low(=mid+1)记住位置,以便后面统一处理。
查找算法时间复杂度为O(logn),而插入时的移动操作时间复杂度为O(n),若用顺序查找,则查找的时间复杂度亦为O(n)。
2.解答:
(1)顺序表
分析:
将顺序表的第一个元素与最后一个元素互换,第二个元素与倒数第二个元素互换。
void
invert(SeqList
*L,
int
*num)
{
j;
ElemType
tmp;
for(j=0;
j<
=(*num-1)/2;
j++)
{tmp=L[j];
L[j]=L[*num-j-1];
L[*num-j-1]=tmp;
(2)单链表
invert(LinkList
L)
{
Node
*p,*q,*r;
if(L->
next==NULL)
return;
/*链表为空*/
p=L->
p->
next=NULL;
/*摘下第一个结点,生成初始逆置表*/
while(q!
=NULL)
/*从第二个结点起依次头插入当前逆置表*/
r=q->
next=L->
L->
q=r;
3.解答:
(1)定位LOCATE(L,X)
在带头结点类单链表上实现的算法为:
intlocate_lklist(lklisthead,datatypex)
/*求表head中第一个值等于x的的序号,不存在这种结点时结果为0*/
{p=head->
j=1;
/*置初值*/
while((p!
=NULL)&
(p->
data!
=x))
{p=p->
j++}/*未达表结点又未找到值等于X的结点时经,继续扫描*/
if(p->
data==x)return(j);
elsereturn(0);
在无头结点的单链表上实现的算法为:
intWlocate(lklisthead,datatypeX)
/*求表head中第一个值等于x的结点的序号。
不存在这种结点时结果为0*/
{p=head;
j=1;
if(p->
data==X)return(j);
(2)按序号查找find(L,i)
在带头结点的单链表上实现的算法为:
pointerfind_lklist(lklisthead,inti);
{j=1;
p=head->
while((j<
1)&
(p!
=NULL)){p=p->
j++}
if(i==j)return(p);
elsereturn(NULL);
p=head;
(3)、插入INSERT(L,X,i)
在带头结点单链表上实现的算法为:
voidinsert_lklist(lklisthead,datatypex,intI)
/*在表haed的第i个位置上插入一人以x为值的新结点*/
{p=find_lklist(head,i-1);
/*先找第i-1个结点*/
if(p==NULL)reeor(“不存在第i个位置”)/*若第i-1个结点不存在,退出*/
else{s=malloc(size);
s->
data=x/*否则生成新结点*/
next/*结点*p在链域值传给结点*s的链域*/
next=s;
/*修改*p的链域*/
voidWinsert(lklisthead,dataytpeX,inti)
{if(i<
=0)error(“i<
=0”);
else{s=malloc(size);
data=X;
/*否则生成新结点*/
if(i==1){s->
next=head;
head=s;
else{p=wfind_lklist(lklisthead,i-1);
if(p==NULL)error(“i>
n+1”);
else{s->
(4)删除DELDTE(L,i)
voiddelete_lklist(lklisthead,inti)/*删除表head的第i个结点*/
{p=find_lklist(head,i-1)/*先找待删结点的直接前驱*/
if((p!
==NULL)&
next!
=NULL))/*若直接前趋存在且待结点存在*/
(q=p->
/*q指向待删结点*/
next=q->
next/*摘除待结点*/;
free(q);
/*释放已摘除结点q*/
elseerror(“不存在第i个结点”)/*否则给出相关信息*/
voidWdelete(lklisthead,inti)
/* 删除表head的第i个结点,若该链表仅有一个结点时,赋该结点指针NULL*/
=0)error(“I<=0”
else{if(i==0){q=head;
head=head->
else{p=wfind_lklist(head,i-1);
/*找链表head中第i-1结点指针*/
if(p!
=NULL)
{q=p->
p->
free(q);
}
elseerror(“不存在第I个结点”);
4.【解答】算法如下:
LinkList
merge(LinkList
A,
LinkListB,
LinkList
C)
{Node
*pa,*qa,*pb,*qb,*p;
pa=A->
/*pa表示A的当前结点*/
pb=B->
p=A;
/*利用p来指向新连接的表的表尾,初始值指向表A的头结点*/
while(pa!
=NULL
&
pb!
/*利用尾插法建立连接之后的链表*/
qa=pa->
qb=qb->
next=pa;
/*交替选择表A和表B中的结点连接到新链表中;
*/
p=pa;
next=pb;
p=pb;
pa=qa;
pb=qb;
if(pa!
/*A的长度大于B的长度*/
if(pb!
/*B的长度大于A的长度*/
C=A;
Return(C);
5.[题目分析]在顺序存储的线性表上删除元素,通常要涉及到一系列元素的移动(删第i个元素,第i+1至第n个元素要依次前移)。
本题要求删除线性表中所有值为item的数据元素,并未要求元素间的相对位置不变。
因此可以考虑设头尾两个指针(i=1,j=n),从两端向中间移动,凡遇到值item的数据元素时,直接将右端元素左移至值为item的数据元素位置。
voidDelete(ElemTypeA[],intn)
∥A是有n个元素的一维数组,本算法删除A中所有值为item的元素。
{i=1;
j=n;
∥设置数组低、高端指针(下标)。
while(i<
j)
{while(i<
j&
A[i]!
=item)i++;
∥若值不为item,左移指针。
if(i<
j)while(i<
A[j]==item)j--;
∥若右端元素值为item,指针左移
j)A[i++]=A[j--];
[算法讨论]因元素只扫描一趟,算法时间复杂度为O(n)。
删除元素未使用其它辅助空间,最后线性表中的元素个数是j。
若题目要求元素间相对顺序不变,请参见本章三、填空题25的算法。
6.分析设置两个指针,分别指向*S及其后继,然后按循环链表特性,顺序往下查找*s的
直接前趋,找到后删除;
voidDELETE_Xlklist(lklistS)
{p=s;
while(q->
nest!
=s)
{p=q;
q=q->
7.分析:
在链表L中依次取元素,若取出的元素是字母,把它插入到字母B中,然后在L中删除该元素;
若取出的元素是数字,把它插入到数字链D中,然后在L中删除该元素。
继续取下一个元素,直到链表的尾部。
最后B、D、L中分别存放的是字母字符、数字字符和其它字符。
设原表有头结点、头指针L,新建数字字符链D,字母字符链B,其它字符链R。
voidDISM_lklist(lklistL,lklistD,lklistB,lklistR)
{D=malloc(sizeof(int));
D->
next=D;
/*建D循环链表头结点*/
B=malloc(sizeof(char));
B->
next=B;
/*建B循环链表头结点*/
p=L;
q=p->
=null)
{if((q->
data<
=’9’)&
(q->
=’0’))
{p->
/*在表L中摘除q结点*/
q->
next=D->
/*将q结点插入D中*/
/*移动q指针*/
elseif(q->
=’z’)&
=’a’)||(q->
=’a’))
/*在表L中删除q结点*/
next=B->
/*将q结点插入B中*/
}else{p=q;
}/*移动q指针*/
next=L;
R=L;
/*使R为循环表*/
8.约瑟夫环问题
【解答】算法如下:
typedefstructNode
{
intpassword;
intnum;
structNode*next;
}
Node,*Linklist;
voidJosephus()
LinklistL;
Node*p,*r,*q;
intm,n,C,j;
L=(Node*)malloc(sizeof(Node));
/*初始化单向循环链表*/
if(L==NULL){printf("
\n链表申请不到空间!
"
);
return;
L->
r=L;
printf("
请输入数据n的值(n>
0):
scanf("
%d"
&
n);
for(j=1;
j++)
/*建立链表*/
p=(Node*)malloc(sizeof(Node));
if(p!
请输入第%d个人的密码:
j);
C);
password=C;
num=j;
r->
next=p;
r=p;
printf("
请输入第一个报数上限值m(m>
m);
*****************************************\n"
出列的顺序为:
\n"
q=L;
while(n!
=1)
/*计算出列的顺序*/
while(j<
m)
/*计算当前出列的人选p*/
q=p;
/*q为当前结点p的前驱结点*/
p=p->
j++;