数据结构课程课后习题答案.docx
《数据结构课程课后习题答案.docx》由会员分享,可在线阅读,更多相关《数据结构课程课后习题答案.docx(22页珍藏版)》请在冰豆网上搜索。
![数据结构课程课后习题答案.docx](https://file1.bdocx.com/fileroot1/2023-1/5/5b0df049-e284-4da8-b114-c9b0d03bb3ef/5b0df049-e284-4da8-b114-c9b0d03bb3ef1.gif)
数据结构课程课后习题答案
数据结构课程课后习题答案
|
|A.一对多b.多对多c.多对一d.一对一答案:
D
(2)与计算机无关的是数据的()结构A.存储物理学C.逻辑d.物理和存储a.C
(3)算法分析的目的是()A.找出数据结构的合理性b.研究算法中输入和输出之间的关系C.分析算法的效率以提高d的可理解性和文档化。
答案:
C
(4)算法分析的两个主要方面是()A.空间复杂性和时间复杂性b.正确性和简洁性c.可读性和文档d.数据复杂性和程序复杂性a.
(5)计算机算法指的是()A.计算方法b.排序方法C.求解问题的有限操作序列d.调度方法a:
C
(6)计算机算法必须具有五个特征,即输入、输出和()A.可行性、可移植性和可扩展性B.可行性、确定性和有限性c.确定性、有限性和稳定性d.易读性、稳定性和安全性a:
B2。
填空
(1)数据结构包括数据①、数据②和数据③三个方面答:
①逻辑结构②存储结构③操作
(2)数据结构根据逻辑结构可分为两类,分别是①和②答:
①线性结构②非线性结构③数据结构形式上定义为(D,R),其中D是①的有限集合,R是D的②有限集合
数据结构简明教程
答案:
①数据元素②关系(4)在一个线性结构中,第一个节点①在该节点之前,其他每个节点都有且只有一个在前的节点;最后一个节点
(2)是后续节点,每个其他节点只有一个后续节点。
回答:
①否②否(5)在树形结构中,根节点没有①节点,每隔一个节点就有且只有②前驱节点;叶节点没有3个节点,每个其他节点的后续节点数可以是4个
A:
①前驱②1③后继④任意数量的
(6)在图结构中,每个节点的前驱节点和后继节点的数量可以是()答:
对于任意数量的
(7)个数据,主要有四种存储结构,分别是①、②、③和④存储结构答:
①序列②链③索引④散列
(8)一个算法的效率可分为①效率和②效率答:
①时间②空间
3。
简短回答
(1)数据结构和数据类型这两个概念有什么区别吗?
答:
简单地说,数据结构定义了一组根据特定关系绑定在一起的数组元素数据类型不仅定义了一组数据元素,还定义了一组对它们的操作
(2)简述线性结构、树形结构和图形结构的区别
a:
线性结构反映节点之间的逻辑关系是一对一的,树线性结构反映节点之间的逻辑关系是一对多的,而图反映结构中节点之间的逻辑关系是多对多的
(3)提供有由二进制组表示的数据逻辑结构S=(D,R),其中d={a,b,...,i},r={(a,b),(a,c),(c,d),(c,f),(f,h),(d,e),(f,g),(h,i)},相对于关系r,哪些节点是起始节点,哪些节点是终止节点?
A:
逻辑结构是树形结构,其中节点A没有被称为根节点的前节点,节点B、E、G和我没有被称为叶节点的末端节点的后继节点。
(4)以下的函数是算法中语句的执行频率,n是问题规模,给出了相应的时间复杂度:
T1(n)=nlog2n-1000log2n2(n)=nlog23-1000log2n3(n)=N2-1000log2n
4(n)=2nlog2n-1000log2n
3a:
T1(n)=O(nl(5)分析以下程序段中循环语句的执行时间
intj=0,s=0,n=100do{
j=j+1;s=s+10*j;
}而(jdata){}
否则返回0;
pre=p;p=p->下一个;
//如果序列是正的,继续判断下一个节点//前,P同步向后移动//前点到第一个数据节点
//p点到后继节点
}
练习和参考答案(6)有一个由整数元素建立的单个链表A,并且设计了一个算法将其分成两个单个链表A和因此,单个链表包含所有偶数节点,单个链表包含所有奇数节点,并且保持原始的相对顺序
解决方案:
采用重新单链表的方法。
因为要保持相对顺序,所以采用尾部插入法来建立新的表a和表bp用于遍历原始单链表的所有数据节点。
如果是偶数个节点,则链接到a。
如果是奇数个节点,则链接到b相应的算法如下:
空隙分割(切片*ra=a;
B=(SLink*)malloc(sizeof(SLink));//建立首节点Rb=B;{}
ra->next=Rb->next=NULL;
//r始终指向b链表的尾部节点//偶数节点//将*p节点链接到
while(p!
=null)
if(p->数据%2==0){}else{}
//奇数节点//链*p节点到
Rb->next=pinb;Rb=p;p=p->下一个;ra->next=p;ra=p。
p=p->下一个;该算法的时间复杂度为0(n),空间复杂度为0
(1)(7)有一个有序的单链表(从小到大排列),头中的指针为L,设计了一个算法,在单链表中插入一个元素为X的节点,这样链表在插入后仍然是有序的。
解决方案:
首先,建立一个要插入的节点,然后依次与链表中每个节点的数据字段比较大小,找到节点插入的位置,最后插入节点相应的算法如下:
顺序列表中的void(幻灯片*
s=(幻灯片*)malloc(sizeof(幻灯片));//建立要插入的节点s->数据=x;s->下一个=空;
if(L==NULL||xdata)//如果单个链表为空或x小于第一个节点的日期字段{}否则{
q=L;
//找到插入位置,p指向要比较的节点,q指向前体节点
p=q->下一个p;
9
s->next=L;L=s。
//将*s节点插入头节点。
数据结构简明教程
}
}
同时(P!
=空p=p->下一个;
//如果x小于p
s->next=p所指示的节点的数据字段值;q->next=s;
(8)有一个链表L,其中可能出现重复范围的节点。
设计了一种删除重复范围节点的算法。
并分析了算法的时间复杂度
解决方案:
用p遍历单个链表,用r遍历*p节点后的节点,q总是指向*r节点的直接前身节点,如果r->数据==p->数据,删除*r节点,否则,q和r同步移回一个节点相应的算法如下:
空dels1(切片*同时(p!
=NULL){}
q=p;r=q->下一个;同时(r!
=NULL){}
p=p->下一个;
if(r->data==p->data)//r指向已删除的节点{}否则{}
q=r;r=r->下一个;t=r->下一个;q->next=t;免费(r);r=t。
该算法的时间复杂度为0(N2)
(9)有一个升序单链表(允许有重复范围的节点),并设计了一个算法来删除有重复范围的节点。
并分析了算法的时间复杂度
解决方案:
因为它是一个有序表,所以具有相同值域的节点都是相邻的递增单链表由p遍历,如果*p节点的取值范围等于其下一个节点的取值范围,则删除后一个节点相应的算法如下:
空delts(切片*同时(p->下一个!
=null){
if(p->data==p->next->data)
//node
}
}
{}
elsep=p->next发现重复值;
q=p->next;自由(q);
练习题和参考答案//q指向具有此重复值的节点//delete*q节点
p->next=q->next;
该算法的时间复杂度为0(n)
(10)有一个双链表l,并设计了一个算法来查找具有第一个元素值x的节点,并将其与后续节点交换
解决方案:
首先找到元素值为x的节点*p,q指向其后继节点。
本主题是将节点*p移动到节点*q,实现过程是:
删除节点*p,然后将其插入节点*q。
相应的算法如下:
intswap(dlink*l,elemtypex){dlink*p=l->next,*q;}
while(p!
=空
//找不到值为X的节点//值为X*p//q的节点指向*p//*p节点的后继节点不是尾节点
RETUR0;
q=p->next;if(q!
=null){}else
//*p节点是尾节点
//不能与后续节点交换,返回0
return0;
if(p==NULL)否则
p->前->后=q;//删除*p节点q->优先级=p->优先级优先;p->next=q->next;如果(q->下一个!
=NULL)
q->下一个->前一个=p;q->next=p;p->先验=q;返回1;
//在*q节点中插入*p节点后,
(11)针对n(n≥1)个数据节点的循环单链表L,设计了一种反转所有节点的算法解决方案:
用头插入法重建循环单链表的思想是先建立一个空的循环单链表,用P遍历所有数据节点,每次在前端插入*p个节点相应的算法如下:
voidreverse(幻灯片*
11
数据结构简明教程
}
L->next=L;同时(p!
=L){}
q=p->下一个;p->下一个=L->下一个;L->下一个=p;p=q;
//将*p节点插入前端
//创建一个空的循环单链表
计算机实验问题2
两个整数集存储在一个有序的单链表中。
尽可能高效地设计一个算法,找出两个集合的并、交和差集并用相关数据进行测试
#include#include\
voidUnion(SLink*L1,SLink*L2,SLink*
L3=(SLink*)malloc(sizeof(SLink));tc=L3p=L1->下一个;q=L2->下一个;
while(p!
=NULLs->数据=p->数据;TC->next=s;tc=s。
s=(SLink*)malloc(sizeof(SLink));s->数据=q->数据;TC->next=s;tc=s。
q=q->下一个;
s=(SLink*)malloc(sizeof(SLink));s->数据=p->数据;TC->next=s;tc=s。
p=p->下一个;
//unionset
}
}
while(p!
=NULL){}
while(q!
=空){}
tc->下一个=空;
s=(SLink*)malloc(sizeof(SLink));s->数据=q->数据;TC->next=s;tc=s。
q=q->下一个;
s=(SLink*)malloc(sizeof(SLink));s->数据=p->数据;TC->next=s;tc=s。
p=p->下一个;}
p=p->下一个;q=q->下一个;
练习题和参考答案无效交集(切片*L1,切片*L2,切片*
L3=(切片*)malloc(sizeof(切片));tc=L3p=L1->下一个;q=L2->下一个;
while(p!
=NULL
if(p->数据){}
p=p->下一个;q=q->下一个;
//p->数据=q->数据
s=(SlInk*)malloc(sizeof(SlInk));s->数据=p->数据;TC->next=s;tc=s。
p=p->下一个;q=q->下一个;
elseif(p->数据>q->数据)else
//交集
//差集
13
数据结构简明教程
{}
voidmain(){
slink*A,*B,*C,*D,*E;
e类型a[]={1,3,6,8,10,20};创建列表器(A,A,6);
//表
printf(\seta:
\elemtypeb[]={2,5,6,10,16,20,30})是通过尾部插值建立的;创建列表器(B,B,7);
//表
printf(\设置B:
\printf(\查找A,B联合C\\n\Union(A,B,C));
//查找A和B的并集C
printf(\设置C:
\printf(\查找A和B的交集C\\n\交集(A,B,D));
//查找a和b联合D
printf(\setd:
\slice*p,*q,*s,*tc
L3=(SlInk*)malloc(sizeof(SlInk));tc=L3p=L1->下一个;q=L2->下一个;
while(p!
=NULL
s=(SLink*)malloc(sizeof(SLink));s->数据=p->数据;TC->next=s;tc=s。
p=p->下一个;
if(p->数据){}
elseif(p->数据>q->数据){}
q=q->下一个;
//p->数据=q->数据p=p->下一步;q=q->下一个;else
s=(SlLink*)malloc(sizeof(SlLink));s->数据=p->数据;TC->next=s;tc=s。
p=p->下一个;
}
printf(\查找A,B差集E\\n\Subs(A,B,E);
练习题和参考答案//查找A和b差集E
printf(\集E:
\DestroyList(A);销毁清单(B);删除列表(C);删除列表(D);删除列表(E);
习题3
1。
(1)堆选择题中元素的进入和退出原则是()A.先入先出B.后进先出c.堆栈为空,然后d.堆栈已满,然后a:
B
(2)如果堆栈的堆栈条目序列为a、B、c、d(即元素a-d按顺序通过堆栈),则堆栈获得的输出序列不能为()
a.a,b,c,db.d,c,b,ac.a,c,d,bd.d,a,b,c
a:
D
(3)如果堆栈条目序列是a,b,c,d,e,那么堆栈的不可能输出序列是()众所周知,一个堆栈的堆栈入口序列是1,2,3?
,n,其输出序列的第一个元素是i(1≤i≤n),则第j(1≤j≤n)个pop元素是()
a.ib.n-IC.j-I+1d.不确定答案:
D
(5)如果顺序堆栈st的顶部指针最初为-1,并且堆栈空间大小为MaxSize,则确定st堆栈为空的条件为()
aST.top==-1bST.top!
=-1摄氏度!
A:
(6)如果顺序堆栈st的顶部指针最初为-1,并且堆栈空间大小为MaxSize,则确定st堆栈已满的条件为
A.st.top!
=-1街顶==-1街顶!
=MaxSize-1D.ST.top==MaxSize-1a:
D
(7)队列中元素的进入和退出策略是()A.先入先出,b.后进先出,c.栈空,然后进,d.栈满,然后出
15
数据结构简明教程
a:
A
(8)元素A,b,c,d在按顺序进入队列qu后是
(1)在团队的最前面,和
(2)在团队的最后面
A.ab.b
c.c.D.D.A:
①A②D
(9)如果队列的输入序列是1234,则队列的可能输出序列是()
a.4321B.1234c.1432d.3241a:
B
(10)循环队列qu的队列满状态(队列头指针指向队列头元素的前一个位置,队列尾指针指向队列尾元素的后一个位置)是()A.(qu.front+1)%MaxSiZe==(qu.front+1)%MaxSiZe
B。
循环队列的队列空状态(队列头指针指向队列头元素的前一个位置,队列尾指针指向队列尾元素的位置)是()A.(qu.front+1)%MaxSiZe==(qu.front+1)%MaxSiZe
B。
假设循环队列中数组的下标为0~n-1,它的头指针和尾指针分别为f和r(头指针f指向头元素的前一个位置,尾指针r指向尾元素的位置),它的元素号为()
a.r-fb.r-f-1c。
(r-f)%n+1d。
(r-f+n)%nada:
D
(13)具有分别堆叠或排队的四个数据元素a、b、c和d。
在堆栈或队列输入期间,一次按A、B、C和d的顺序输入一个元素假设堆栈或团队的初始状态为空现在要执行的堆栈操作是推栈两次,推栈一次,推栈两次,推栈一次。
此时,从第一堆栈获得的元素是
(1),从第二堆栈获得的元素是
(2);同样,这四个数据元素的团队操作被认为是进入团队两次,离开团队一次,进入团队两次,离开团队一次。
这时,第一次从团队中得到的元素是(3),第二次从团队中得到的元素是(4)操作之后,堆栈中或团队中最终会有更多的元素。
①~④:
A.ab.B.c.c.D.D⑤:
A.1b.2c.3d.0a:
①B②D③A④B⑤B
练习问题和参考答案(14)将堆栈s和队列q的初始状态设置为空,元素e1~e6按顺序通过堆栈s,一个元素退出后立即进入队列q,如果退出的6个元素的顺序为e2、e4、e3、e6、e5、e1,则堆栈s的容量应为
A.5
a:
c
b.4
c.3
d.2
2。
填充问题
(1)堆栈是一个特殊的线性表。
允许插入和删除操作的一端称为
(1)不允许插入和删除操作的结尾称为
(2)
a:
①堆栈顶部②堆栈底部
(2)堆栈的输入序列是12345,输出序列是12345,进出堆栈的操作是()回答:
1推,1推,2推,2推,3推,3推,4推,4推,5推,5推
(3)有5个元素,它们的堆叠顺序是a、b、c、d、e。
在所有可能的堆叠顺序中,元素c和d(即c第一和d第二)的顺序是()
a:
CDBAE、CDEBA、CDBEA
(4)顺序堆栈使用数据[0..n-1]要存储数据,堆栈的顶部指针是top,它的初始值是0,那么元素x进入堆栈的操作是()
a:
数据[top]=x;top++;
(5)顺序堆栈使用数据[0..n-1]要存储数据,堆栈的顶部指针是top,其初始值是0,那么pop元素x的操作是()
a:
顶部-;x=数据[顶部];(6)()
a:
队列
(7)具有数组A[0..m]作为循环队列的存储空间,front是head指针(指向head元素的前一个位置),rear是tail指针(指向tail元素的位置),然后元素x执行入队操作()
a:
原因=(原因+1)%(m+1);[后方]=x;
(8)配有阵列A[0..m]作为循环队列的存储空间,front是head指针(它指向head元素的前一个位置),而rear是tail指针(它指向tail元素的位置),那么将元素去队列并保存到x的操作是()
a:
front=(front+1)%(m+1);x=[后方];
3。
简短回答
(1)简要解释了线性表格、堆栈和团队之间的异同
a:
相同点:
都属于线性结构,可以存储在序列或链表中;堆栈和队列是两种特殊的线性表,即限制线性表,它只限制插入和删除操作。
的不同之处在于
(1)运算规则不同,线性表是随机存取的,堆栈只允许在一端进行插入和删除操作,所以是后进先出法;;队列是先进先出的,只允许一端插入,另一端删除。
(2)不同用途:
堆栈用于子进程调用和字段保护,队列用于
17
数据结构简明教程
、指令寄存器等操作
(2)序列组如何产生“假溢出”?
我如何知道循环队列是空的还是满的?
A:
一般一维数组队列的尾部指针已经到达数组的上限,可以没有队列条目,但是数组中仍然有空的位置,这叫做“假溢出”
采用循环队列解决假溢出另外,循环队列是空的还是满的解决方案如下:
①设置一个布尔变量来区分队列是满的还是空的;
②浪费一个空间元素来区分满队和空队(3)使用计数器记录队列中的元素数量(即队列长度)
通常采用方法2,使队首指针指向队首元素的前一个位置,队尾指针指向队尾元素的后一个位置,从而判断循环队列的队列空标志为:
前=后,队列满标志为:
(后+1)%MaxSize=前
4。
算法设计问题
(1)假设一个顺序堆栈存储结构,一个算法被设计为通过使用堆栈的基本操作返回指定堆栈的底部元素,并且要求堆栈中的元素保持不变。
在这里,我们只能使用堆栈st的基本操作来完成,并且我们不能直接使用st.data[0]来获取堆栈底部的元素。
解决方案:
假设一个顺序堆栈结构首先,从堆栈中移除st中的所有元素。
临时堆栈tmpst用于存储从st堆栈中移除的元素。
最后一个元素是请求。
然后,临时堆栈tmpst中的元素被一个接一个地从堆栈中移除并推入st,从而恢复st堆栈中的原始元素。
相应的算法如下:
intgetbottom(sqstackst,elemtypesqstacktmpst
//definetemporarystack//initializetemporarystack//emptystack返回0
//temporarystacktmpst包含ststack中的反转元素
InitStack(tmpst);if(StacKempty(ST)){}
while(!
StacKempty(tmpST)){}
return1;
//返回1表示成功
Pop(tmpst,e);推动(st,e)。
//恢复st堆栈的原始内容
返回0;Pop(st,x);推送(tmpst,x)。
while(!
StackEmpty(st))
(2)设计了一种算法,该算法使用顺序堆栈来反向输出单个链表l中的所有元素
解决方案:
这个问题不需要改变单链表l的结构设置一个顺序堆栈st,遍历单个链表并将所有元素推入堆栈,然后循环堆栈直到它为空并输出堆栈中的所有元素。
相应的算法如下:
空反向显示(slink*l){
elemtypex;结构节点{
电子类型数据[MaxSize];
}
inttop;
//定义序列堆栈
练习问题和参考答案}st
ST.top=-1;
链接*p=L->下一个;同时(p!
=空){}
while(st.top!
=-1){}
printf(\
x=ST.data[ST.top];ST.top-;
printf(\
//堆栈不是空循环,输出堆栈中的所有元素
st.top++;
ST.data[ST.top]=p->data;p=p->下一个;
//遍历单个链表,将所有元素放在堆栈
(3)上以设计一个循环队列,分别使用前端和后端作为团队头指针和尾指针,并使用标志
标记来标识队列可能是空的(0)还是满的
(1),因此添加前端==后端可用作团队为空或满的条件。
要求为队列设计相关的基本计算算法。
解决方案:
设计的队列类型如下:
typedefstruct
{elemtypedata[maxsize];
int前部、后部;int标记;
//团队头指针和尾指针
//