数据结构习题解答.docx

上传人:b****5 文档编号:8007446 上传时间:2023-01-27 格式:DOCX 页数:16 大小:163.03KB
下载 相关 举报
数据结构习题解答.docx_第1页
第1页 / 共16页
数据结构习题解答.docx_第2页
第2页 / 共16页
数据结构习题解答.docx_第3页
第3页 / 共16页
数据结构习题解答.docx_第4页
第4页 / 共16页
数据结构习题解答.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

数据结构习题解答.docx

《数据结构习题解答.docx》由会员分享,可在线阅读,更多相关《数据结构习题解答.docx(16页珍藏版)》请在冰豆网上搜索。

数据结构习题解答.docx

数据结构习题解答

习题一

1填空题

(1)(数据元素、或元素、或结点、或顶点、或记录)是数据的基本单位,在计算机程序中作为一个整体进行考虑和处理。

(2)(数据项、或字段)是数据的最小单位,(数据元素)是讨论数据结构时涉及的最小数据单位。

⑶从逻辑关系上讲,数据结构主要分为(集合)、(线性结构)、(树结构)和(图)。

(4)数据的存储结构主要有(顺序存储结构)和(链式存储结构)两种基本方法,不论哪种存储结构,都要存储两方面的内容:

(数据元素)和(它们之间的关系)。

⑸算法具有5个特性,分别是(输入)、(输出)、(有穷性)、(确定性)、(可行性)。

(6)算法的描述方法通常有(自然语言)、(流程图)、(程序设计语言)、(伪代码)4种,其中,(伪代码)被称为算法语言。

(7)一般情况下,一个算法的时间复杂度是算法(输入规模)的函数。

(8)设待处理问题的规模为n,若一个算法的时间复杂度为一个常数,则表示成数量级的形式为(0

(1)),

若为n*log25n,则表示成数量级的形式为(0(n*log2n))。

2.选择题:

⑴C,D

(2)B(3)B⑷A(5)D(6)A(7)C(8)C,E

习题二

1.填空题

(1)在顺序表中,等概率情况下,插入和删除一个元素平均需移动(表长的一半)个元素,具体移动元

素的个数与(表的长度)和(数据元素所在的位置)有关。

(2)一个顺序表的第一个元素的存储地址是100,每个数据元素的长度是2,则第5个数据元素的存

储地址是(108)。

(3)设单链表中指针p指向单链表的一个非空结点A,若要删除结点A的直接后继,则需要修改指针的操作为(p->next=(p->next)->next,或者q=p->next;p->next=q->next)。

(4)单链表中设置头结点的作用是(方便运算,减少程序的复杂性,使得空表和非空表处理统一)。

⑸非空的循环单链表由头指针head指示,则其尾结点(由指针p所指)满足(p->next=head)。

⑹在有尾指针rear指示的循环单链表中,在表尾插入一个结点s的操作序列是(s->next=rear->next;rear->next=s;rear=s),删除开始结点的操作序歹卩是(q=rear->next->next;rear->next->next=q->next;deleteq;)。

注:

假设此循环单链表有表头结点

(7)一个具有n个结点的单链表,在p所指结点后插入一个新结点s的时间复杂性为(O

(1));在给定值x的结点后插入一个新结点的时间复杂性为(O(n))。

(8)可由一个尾指针惟一确定的链表有(循环链表)、(双链表)、(双循环链表)。

2.选择题:

⑴A,B

(2)D(3)B⑷A(5)A(6)D(7)B(8)B(9)C(10)B(11)B(12)D

(13)A(14)A

5.算法设计

(1)设计一个时间复杂度为O(n)的算法。

实现将数组A[n]中所有元素循环左移k个位置。

算法思想:

要使◎…阪ak+「・a->ak+1…aa1…a,可以先让a1••愉ak+「・a->sk…aian・・・a+1,再让ak…aan•••a+1->ak+1…询1…a,参见第1章16页的思想火花

算法:

voidconverse(Ta[],inti,intj){

for(s=i;s<=(i+j)/2;s++)//将数组a中从i至打中的元素倒置{temp=a[s];a[s]=a[j-s+i];a[j-s+i]=temp;}}

voidmove(Ta[],k)

{converse(a,0,k-1);//3次调用函数converse

converse(a,k,n-1);

converse(a,0,n-1);

}

⑵已知数组A[n]中的元素为整型,设计算法将其调整为左右两部分,左边所有元素为奇数,右边所有元素为偶数,并要求算法的时间复杂度为O(n).

解法1:

voidtiaozhen(TA[],intn)

{s=0;t=n-1;

while(s

{while(A[s]%2!

=0)s++;//s=s+1

while(A[t]%2==0)t--;

if(s

}}或voidtiaozhen(TA[],intn)

{s=0;t=n-1;

while(s

{if(A[s]%2!

=0)s++;//s=s+1

elseif(A[t]%2==0)t--;

else{temp=A[s];A[s]=A[t];A[t]=temp;s++;t--;}

}}

(3)试编写在无头结点的单链表上实现线性表的插入操作的算法,并和带头结点的单链表上的插入操

作的实现进行比较

voidLinkList_1:

:

lnsert(inti,Tx){

if(i<=0)throw"输入的插入位置值小于1";

if(i==1){s=newNode;s->data=x;s->next=first;first=s;}

else{p=first;j=0;

while(p&&jnext;j++;}

if(!

p)throw插入位置值太大";

else{s=newNode;s->data=x;s->next=p->next;p->next=s;}

}

}

(4)试分别以顺序表和单链表作存储结构,各写一实现线性表就地逆置的算法。

算法思想:

顺序表的程序参见题

(1)的converse单链表的程序如下,设单链表有表头结点.

voidLinkList:

:

converse()

{p=first->next;

first->next=NULL;

while(p){

q=p->next;p->next=first->next;

first->next=p;p=q;

}

}

(5)假设在长度大于1的循环链表中,既无头结点也无头指针,s为指向链表中某个结点的指针,试编写算法删除结点s的前驱结点。

voidLinkList:

:

deleteS(Node*s)

{p=s;

while(p->next->next!

=s)p=p->next;

{q=p->next;p->next=q->next;

deleteq;

}

(6)已知一单链表中的数据元素含有三类字符:

字母、数字和其它字符。

试编写算法,构造三个循环链表,使每个循环链表中只含同一类字符。

算法思想:

1)构造3个带表头结点的循环链表,分别为zifu,shuzi和qita;

2)遍历单链表,按单链表中的当前数据元素的分类插入相应的链表

voidfl(Node*zifu,Node*shuzi,Node*qita)

{s=newNode;s->next=s;zifu=s;

s=newNode;s->next=s;shuzi=s;

s=newNode;s->next=s;qita=s;

a=zifu;b=shuzi;c=qita;

p=first->next;//设单链表带头结点while(p){q=p;p=p->next;

if((q->data>='a'&&q->data<='z')||(q->data>='A'&&q->data<='A'))

{q->next=a->next;a->next=q;a=q;}

elseif(q->data>='0'&&q->data<=9)

{q->next=b->next;b->next=q;b=q;}

else{q->next=c->next;c->next=q;c=q;}

}

deletefirst;

}

(7)设单链表以非递减有序排列,设计算法实现在单链表中删除相同的多余结点解:

voidLinkList:

:

deleteALL()

{p=first->next;//假设单链表带表头结点。

while(p)

{if(p->next!

=NULL&&p->next->data==p->data)

{q=p->next;p->next=q->next;deleteq;}

elsep=p->next;}

}

(8)判断带头结点的双循环链表是否对称。

解boolLinkList:

:

equal(DulNode*first)

{p=first->next;q=first->prior;

while(p!

=q&&p->prior!

=q)

if(p->data==q->data)

{p=p->next;q=q->prior;}

else{return0;}

return1;

}

习题三

1填空题

(1)设有一个空栈,栈顶指针为1000H,经过push、push、pop、push、pop、push、push后,栈顶指针为(1003H)。

(2)栈结构通常采用的两种存储结构是(顺序存储结构和链接存储结构顺序栈和链栈),其判定栈空的

条件分别是(top=-1,top=NULL),判断栈满的条件分别是(top=MaxSize-1,内存满/内存无可用空间)。

(3)(栈)可作为实现递归函数调用的一种数据结构。

⑷表达式a*(b+c)-d的后缀表达式是(abc+*d-)。

(5)栈和队列是两种特殊的线性表,栈的操作特性是(后进先出),队列的操作特性是(先进先出),栈和

队列的主要区别在于(插入、删除运算的限定不一样)。

⑹循环队列的引入是为了克服(假溢出)。

⑺一维数组Data[n]用来表示循环队,队头指针front和队尾指针rear定义为整型变量,计算队中元素个数的公式是((rear-front+n)%n)。

(8)用循环链表表示的队列长度为n,若只设头指针,则出队和入队的时间复杂度分别是(0

(1))和

(0(n))。

2.选择题:

⑴C

(2)D(3)C⑷B(5)B(6)B(7)D(8)A(9)C

4•解答下列问题

(1)①不可以,因为有序列C,A,B.

②可以,push,push,push,pop,pop,pop,push,pop,push,pop.

⑵见书本

(3)栈顶元素是6,栈底元素是1.

(4)队尾兀素是9,队头兀素是5.

(5)①③④合法,②不合法.

习题四

1.填空题

(1)串是一种特殊的线性表,其特殊性体现在(数据元素的类型为字符型)。

(2)两个串相等的充分必要条件是(它们的长度相等且对应位置的字符相同)。

(3)数组通常只有两种运算,分别是(存取)和(修改),这决定了数组通常采用(顺序存储)结构来实现存储。

⑷(1140)

(5)设有一个10阶的对称矩阵A采用压缩存储,第一个元素A[0][0]的存储地址为d,每个元素占用1

个地址空间,则元素A[8][5]的存储地址为(d+41)。

(6)稀疏矩阵一般压缩存储方法有两种,分别是(三元组顺序表)和(十字链表)。

2.选择题:

⑴B⑵D,E,K(3)B⑷XXX(5)D⑹C(7)D

5

(2).设计一个求矩阵A=(aj)nxm所有鞍点的算法,并分析最坏情况下的时间复杂度。

算法思想2:

附加两个数组B[n]和C[m],B[i]用来存第i行的最小值,C[j]用来存第j列的最小元素值。

如果A[i][j]=B[i]=C[j],则A[i][j]一定为马鞍点。

viodmaandian2(A[][],intm,intn){

intB[n],C[m],i,j;

for(i=0;i

B[i]=A[i][0];

for(j=1;jA[i][j])B[i]=A[i][j];}

for(j=0;j

C[j]=A[0][j];

for(i=1;i

for(i=0;i

for(j=0;j

if(B[i]==A[i][j]&&C[j]==A[i][j])

cout<

}

算法复杂度:

O(mn)。

从时间复杂度的幕的角度来说这个算法是最好的,因为你求马鞍点必须要搜索所有的A[i][j]。

习题五

1填空题

(1)树是n(n》0)个结点的有限集合。

在一棵非空树中,有(且仅有一个)根结点,其余结点分成m(m>=0)个(互不相交)的有限集合,每个集合又是一棵树。

(2)树中某结点的子树的个数称为该结点的(度),子树的根结点称为这个结点的(孩子结点),该结

点称为其子树根结点的(双亲结点)•

(3)一棵二叉树的第i(i>1)层上最多有(2i-1)个结点,一棵有n(n>0)个结点的满二叉树共有((n+1)/2)个叶子结点和((n-1)/2)个非终端结点。

(4)设高度为h的二叉树只有度为0的和度为2的结点,该二叉树的结点数可能达到的最大值是(2h-1),最小值是(2h-1)。

⑸深度为k的二叉树中,所含叶子的个数最多为(2k-1).

⑹具有100个结点的完全二叉树的叶子结点数为(50)。

⑺已知一棵度为3的树有2个度为1的结点,3个度为2的结点,4个度为3的结点。

则该树有(12)个叶子结点。

(8)某二叉树的前序遍历序列是ABCDEFG中序遍历序列是CBDAFGE则其后序遍历序列是(CDBGFEA)。

(9)在具有n个结点的二叉链表中,共有(2n)个指针域,其中(n-1)个指针域用于指向其左右

孩子,剩下的(n+1)个指针域则是空的。

(10)在有n个叶子的哈夫曼树中,叶子结点总数为(n),分支结点总数为(n-1)。

2.选择题:

(1)D

(2)D(3)B⑷C(5)B,C(6)D(7)A(8)A,B(9)D,A(10)B(11)B(12)C(13)D(14)C

4.解答下列问题

⑶已知一棵度为m的树中:

n1个度为1的结点,n2个度为2的结点,…,nm个度为m的结点,问该树中共有多少个叶子结点?

解:

设该树中共有n0个叶子结点。

则该树中总结点个数为

n=n0+n1+…+m.

而分支数为n-1=n1+2n+3n3+…+mm,所以

n0=1+n2+2n3+…+(m1)nm

⑷已知一棵二叉树的中序和后序序列为CBEDAFIGH口CEDBIFHGAS构造该二叉树

⑸给出叶子结点的权值集合为W={5,2,9,11,8,3,7}的哈夫曼树的构造过程

(3)

5算法设计

(1)设计算法求二叉树的结点个数•

注:

本算法可以用二叉树遍历的所有算法,只要把cout语句换成结点的计数就可以了,但是要注意

递归中的计数变量应该是外部变量。

intnum=0;

intBiTree:

:

count(BiNode*rt){countsub(rt);returnnum;}

voidBiTree:

:

countSub(BiNode*rt){

if(rt!

=NULL){num++;countSub(rt->lchild);countSub(rt->rchild);}

}

其他解法二:

用前序遍历的非递归算法

intBiTree:

:

CountPreOrder(BiNode*rt)

{top=-1;p=rt;num=0;//采用顺序栈s,并假定不会发生上溢

while(p!

=NULL||top!

=-1){

while(p!

=NULL)//找此结点的最左边的后代

{num++;//访问

s[++top]=p;//此结点进栈

p=p->lchild;//转移到左儿子子树

}

if(top!

=-1){p=s[top--];p=p->rchild;}}

returnnum;//cout<

}

(2)设计算法按照前序次序打印二叉树中的叶子结点.

注:

其实按照选择题”的(7)知:

任何一棵二叉树的叶子结点在前序、中序、后序遍历序列中的相对次序肯定不发生改变

解法思想:

使用任何遍历算法,把“cout<data'改成判断此结点是否为叶子结点。

voidBiTree:

:

leaf(BiNode*rt){

if(rt==NULL)return;

else

{if(rt->lchild==NULL&&!

rt->rchild)

cout<data;

PostOrder(rt->lchild);

PostOrder(rt->rchild);

}}

(3)设计算法求二叉树的深度.

注:

本算法也可以用二叉树遍历的所有算法。

但是在用前序和中序算法时要注意深度如何来确定'

intBiTree:

:

depth(BiNode*rt)

{if(rt==NULL)return0;

else{

hl=depth(rt->lchild);

hr=depth(rt->rchild);

return(hl>hr)?

hl+1:

hr+1;

}

(4)设计算法:

输出二叉树后序遍历的逆序.

解法思想:

太简单啦!

前序遍历是先遍历右子树即可.

voidBiTree:

:

PostOrder_1(BiNode*rt){

if(rt==NULL)return;

else{

cout<data;

PostOrder(rt->rchild);

PostOrder(rt->lchild);

}}

(5)以二叉链表为存储结构,编写算法求二叉树中值x的结点的双亲.

voidBiTree:

:

PreOrder_Parent(BiNode*rt){

{top=-1;p=rt;//采用顺序栈s,并假定不会发生上溢

while(p!

=NULL||top!

=-1){

while(p!

=NULL)

{if(rt->lchild!

=NULL&&rt->lchild->data==x)

cout<data;

if(rt->rchild!

=NULL&&rt->rchild->data==x)cout<data;

s[++top]=p;//此结点进栈

p=p->lchild;//转移到左儿子子树

}

if(top!

=-1){p=s[top--];p=p->rchild;}}

}

(6)以二叉链表为存储结构,在二叉树中删除以值x为根结点的子树.

voidBiTree:

:

DeleteX(BiNode*rt,Tx)

{if(rt==NULL)return;

if(rt->data==x){Release(rt);}

else{

DeleteX(rt->lchild,x);

DeleteX(rt->rchild,x);

}}

(7)一棵具有n个结点的二叉树采用顺序存储结构,编写算法对该二叉树进行前序遍历.

算法思想:

套用前序遍历的原程序,注意查找左右孩子结点的地址和判别孩子是否存在的方法。

注:

根结点的下标是1。

voidBiTree:

:

PreOrder_Seq(intrt)

{top=-1;p=rt;//采用顺序栈s,并假定不会发生上溢

while((p<=length)&&(A[p]!

=”))'||top!

=-1){

while((p<=length)&&(A[p]!

=”)){

//找此结点的最左边的后代

cout<

p=2*p;//转移到左儿子子树

}

if(top!

=-1){p=s[top--];p=2*p+1;}

}

}

(8)编写算法交换二叉树中所有结点的左右子树.

解法思想:

使用任何遍历算法,把“cout<data'改成左右孩子指针交换即可voidBiTree:

:

PostOrderChange(BiNode*rt)

{

if(rt==NULL)return;

else

{PostOrder(rt->lchild);

PostOrder(rt->rchild);temp=rt->lchild;rt->lchild=rt->rchild;rt->rchild=temp;

}}

1图中有多少条边?

答:

邻接表中所有边表结点的个数的一半•

2任意两个顶点i和j是否有边相连?

答:

查找第i个边表的结点中是否有邻接点域值为j的结点•如果有,则它们之间有边;否则,无边.

3任意一个顶点的度是多少?

答:

此顶点对应的边表中结点的个数•

⑵n个顶点的无向图,采用邻接矩阵存储,回答下列问题:

1图中有多少条边?

答:

邻接矩阵中所有元素和的一半•

2任意两个顶点i和j是否有边相连?

答:

如果第i行第j列的元素值为1,则它们之间有边;否则,无边.

3任意一个顶点的度是多少?

答:

此顶点对应的行中元素之和.

(3)证明:

生成树中最长路径的起点和终点的度均为1.

证明:

设一棵树的最长路径P=V1V2…v若V1的度至少为2,不妨设u(恋V是它的另外一个邻点。

若u€{Vi,V2,…,kV,则此树中包含圈,矛盾;否则UV1V2…V是一条更长的路,同样矛盾。

所以V1的度为

1.类似可以证明Vk的度为1.

⑸图6-50所示是一个无向带权图,请分别用Prim算法和Kruscal算法求最小生成树。

习题7

1.填空题

(1)顺序查找技术适合于存储结构为(各种形式)的线性表,而折半查找技术适合于存储结构为(顺序存储)的线性表,并且表中的元素必须是(有序的)。

(2)设有一个已按各元素值排好序的线性表,长度为125,用折半查找法查找与给定值相等的元素,若查找成功,则至少需要比较

(1)次,至多需要比较(7)次。

⑶对于数列{25,30,8,5,1,27,24,10,20,21,9,28,7,13,15假定每个结点的查找概率相同,若用顺序存储结构组织该数列,则查找一个数的平均比较次数为(8)。

若按二叉排序树组织该数列,则查找

一个数的平均比较次数为(59/15)。

(4)长度为20的有序表采用折半查找,共有(4)个元素的查找长度为3。

(5)假设数列{25,43,62,31,48,56}采用散列函数为H(k)=kmod7,则元素48的同义词是(62)

(6)在散列技术中,处理冲突的主要方法是(开放地址法)和(拉

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 自然景观

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1