数据结构6章习题单号和双号附答案不保证正确.docx
《数据结构6章习题单号和双号附答案不保证正确.docx》由会员分享,可在线阅读,更多相关《数据结构6章习题单号和双号附答案不保证正确.docx(22页珍藏版)》请在冰豆网上搜索。
数据结构6章习题单号和双号附答案不保证正确
《算法与数据结构》第1-6章课堂测验(双号)
一、选择题
1、已知一个栈的进栈序列是1,2,3,…,n,其输出序列是p1,p2,…,pn,若p1=n,则pi的值。
(C)
(A)i(B)n-i
(C)n-i+1(D)不确定
2、设n个元素进栈序列是1,2,3,…,n,其输出序列是p1,p2,…,pn,若p1=3,则p2的值。
(C)
(A)一定是2(B)一定是1
(C)不可能是1(D)以上都不对
3、若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是(B)
D.不确定
4、在下述结论中,正确的是(D)
①只有一个结点的二叉树的度为0;
②二叉树的度为2;
③二叉树的左右子树可任意交换;
④深度为K的完全二叉树的结点个数小于或等于深度相同的满二叉树。
A.①②③B.②③④C.②④D.①④
5、一棵树高为K的完全二叉树至少有(C)个结点。
(A)
–1+1
二、简答题
1简述下列术语:
线性表,顺序表,链表。
答:
线性表是具有相同特性的数据元素的一个有限序列。
用顺序存储方法存储的线性表简称顺序表。
用链式存储方法存储的线性表简称链表。
(这组存储单元可以使连续的,也可以是不连续的)
2何时选用顺序表,何时选用链表作为线性表的存储结构合适?
各自的主要优缺点是什么?
答:
顺序表的主要优点:
没用使用指针,不用花费附加开销
线性表元素的读访问非常简洁便利
链表的主要优点:
无需事先了解线性表的长度
能够适应经常插入删除内部元素的情况
允许线性表的长度有很大变化
不要使用顺序表的场合:
经常插入删除时,不宜使用顺序表
线性表的最大长度也是一个重要因素
不要使用链表的场合:
当读操作比插入删除操作频率大时,不应选择链表
当指针的存储开销,和整个结点内容所占空间相比其比例较大时,应该慎重选择
(不需要经常大量的修改表或需要随机存取的情况下可以选用顺序表;。
相反需要经常大量的修改表,但不是频繁的随机存取的情况下可选用链式表)
3链表所表示的元素是否有序?
如有序,则有序性体现于何处?
链表所表示的元素是否一定要在物理上是相邻的?
有序表的有序性又如何理解?
答:
有序。
有序性体现在通过指针数据元素有序的相连。
物理上不一定要相邻。
4设A和B是两个按元素值递增有序的单链表,写一算法将A和B归并为按按元素值递减有序的单链表C,试分析算法的时间复杂度。
4、例:
什么是队列的上溢现象和假溢出现象?
解决它们有哪些方法?
答:
在队列的顺序存储结构中,设头指针为front,队尾指针rear,队的容量(存储空间的大小)为MaxSize。
当有元素加入到队列时,若rear=MaxSize(初始时rear=0)则发生队列的上溢现象,该元素不能加入队列。
特别要注意的是队列的假溢出现象:
队列中还有剩余空间但元素却不能进入队列,造成这种现象的原因是由于队列的操作方法所致。
解决队列上溢的方法有以下几种:
1)建立一个足够大的存储空间,但这样做会造成空间的使用效率降低。
(2)当出现假溢出时可采用以下几种方法:
①采用平移元素的方法:
每当队列中加入一个元素时,队列中已有的元素向队头移动一个位置(当然要有空闲的空间可供移动);②每当删除一个队头元素时,则依次移动队中的元素,始终使front指针指向队列中的第一个位置;③采用环形队列方式:
把队列看成一个首尾相接的环形队列,在环形队列上进行插入或删除运算时仍然遵循“先进先出”的原则。
”
5、例:
对于顺序队列来说,如果知道队首元素的位置和队列中元素个数,则队尾元素所在位置显然是可以计算的。
也就是说,可以用队列中元素个数代替队尾指针。
编写出这种循环顺序队列的初始化、入队、出队和判空算法。
1设有一个栈,元素进栈的次序为a,b,c。
问经过栈操作后可以得到哪些输出序列?
答:
①cba;②abc;③acb;④bac;⑤bca;
2循环队列的优点是什么?
如何判断它的空和满?
答:
优点:
可以克服顺序队列的“假上溢”现象,能够使存储队列的向量空间得到充分利用。
判断循环队列的空或满不能以头尾指针是否相等来确定,一般是通过以下几种方法:
一是另设一布尔变量来区别队列的空和满。
二是约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满。
三是设置一计数器记录队列中元素的总数,不仅可判别空或满,还可以得到队列中元素的个数
3设有一个静态顺序队列,向量大小为MAX,判断队列为空的条件是什么?
队列满的条件是什么?
答:
队首指针front,一个队尾指针rear
循环队列为空:
front=rear。
循环队列满:
rear==MaxSize-1或front==rear。
5设Q[0,6]是一个静态顺序队列,初始状态为front=rear=0,请画出做完下列操作后队列的头尾指针的状态变化情况,若不能入对,请指出其元素,并说明理由。
a,b,c,d入队
a,b,c出队
i,j,k,l,m入队
d,i出队
n,o,p,q,r入队
其中l,m,n,o,p,q,r均由于队列假溢出问题无法入队
6假设Q[0,5]是一个循环队列,初始状态为front=rear=0,请画出做完下列操作后队列的头尾指针的状态变化情况,若不能入对,请指出其元素,并说明理由。
d,e,b,g,h入队
d,e出队
i,j,k,l,m入队
b出队
n,o,p,q,r入队
⑴假设在树中,结点x是结点y的双亲时,用(x,y)来表示树边。
已知一棵树的树边集合为{(e,i),(b,e),(b,d),(a,b),(g,j),(c,g),(c,f),(h,l),(c,h),(a,c)},用树型表示法表示该树,并回答下列问题:
①哪个是根结点?
哪些是叶子结点?
哪个是g的双亲?
哪些是g的祖先?
哪些是g的孩子?
那些是e的子孙?
哪些是e的兄弟?
哪些是f的兄弟?
②b和n的层次各是多少?
树的深度是多少?
以结点c为根的子树的深度是多少?
①a是根结点;mndfjkl是叶结点;c是g的双亲;c,a是g的祖先;j,k是g的孩子;imn是e的子孙;d是e的兄弟;g,h是f的兄弟;
②b的层次是2;n的层次是5;树的深度是5;以c为根的子树深度是3;
⑵一棵深度为h的满k叉树有如下性质:
第h层上的结点都是叶子结点,其余各层上每个结点都有k棵非空子树。
如果按层次顺序(同层自左至右)从1开始对全部结点编号,问:
①各层的结点数是多少?
②编号为i的结点的双亲结点(若存在)的编号是多少?
③编号为i的结点的第j个孩子结点(若存在)的编号是多少?
④编号为i的结点的有右兄弟的条件是什么?
其右兄弟的编号是多少?
三、算法理解
1、已知P结点是某双向链表的中间节点,画图并写出下列操作的语句序列。
(1)在P结点后插入S结点。
(2)删除P结点的后继结点Q。
结点结构如下:
Prior
Data
Next
(其中Prior、Data、Next分别为前驱节点指针、数据域、后继节点指针。
)
答:
(1)P->Next->Prior=S;S->Next=P->Next;P->Next=S;S->Prior=P;
(2)Q=P->Next;P->Next=P->Next->Next;P->Next->Prior=P;free(Q);
4、假设一棵二叉树的前序序列为EBADCFHGIKJ,中序序列为ABCDEFGHIJK。
请画出该树,并写出后序序列。
(要求写出分析过程)
E(B(A,D(C,)),F(,H(G,I(,K(J,)))))
答:
该树如下
首先,前序序列是以-(根节点)(左子树)(右子树)来排列的,所以在前序树最左边的节点一定是树的根节点,这样我们就可以确定E是根节点。
再来看中序序列,我们知道了E是根节点,便可以从中序序列知道(ABCD)(FGHIJK)分别是E节点的左右子树,再通过前序树得到(BADC)(FHGIKJ)的根节点分别是B与F,以此类推可求得整个树的结构。
后序序列:
ACDBGJKIHFE
7、(8分)假设用于通讯的电文由A、B、C、D、E、F、G、H这8个字母组成,字母在电文中出现的频率为{,,,,,,,},画出这8个字母哈夫曼树并设计哈夫曼编码。
a:
0010b:
10
c:
00000d:
0001
e:
01f:
00001
g:
11h:
0011
7、假设用于通讯的电文仅由8个字母组成,字母在电文中出现的频率百分比分别为7,19,2,6,32,3,21,10。
画出这8个字母哈夫曼树,标出其哈夫曼编码。
答案如上
⑶设有如图6-27所示的二叉树。
①分别用顺序存储方法和链接存储方法画出该二叉树的存储结构。
②写出该二叉树的先序、中序、后序遍历序列。
答:
①顺序存储结构:
链式存储结构
②先序:
abdehkcfgmn
中序:
dbhekafcmgn
后序:
dhkebfmngca
⑷已知一棵二叉树的先序遍历序列和中序遍历序列分别为ABDGHCEFI和GDHBAECIF,请画出这棵二叉树,然后给出该树的后序遍历序列。
后序:
GHDBEIFCA
⑸设一棵二叉树的中序遍历序列和后序遍历序列分别为BDCEAFHG和DECBHGFA,请画出这棵二叉树,然后给出该树的先序序列。
答:
该树如下:
先序遍历:
ABCDEFGH
⑹已知一棵二叉树的中序遍历序列和后序遍历序列分别为dgbaekchif和gdbkeihfca,请画出这棵二叉树对应的中序线索树和后序线索树。
答:
首先还原出这棵树如下:
⑺以二叉链表为存储结构,请分别写出求二叉树的结点总数及叶子结点总数的算法。
解:
(1)求结点数的递归定义为:
若为空树,结点数为0
若只有根结点,则结点数为1;
否则,结点数为根结点的左子树结点数+右子树结点数+1
(2)求叶子数的递归定义为:
若为空树,叶子数为0
若只有根结点,则叶子数为1;
否则,叶子数为根结点的左子树叶子数+右子树叶子数
typedefcharDataType;//定义DataType类型
typedefstructnode{
DataTypedata;
structnode*lchild,*rchild;//左右孩子子树
}BinTNode;//结点类型
typedefBinTNode*BinTree;//二叉树类型
intNode(BinTreeT)
{//算结点数
if(T)
if(T->lchild==NULL)&&(T-->rchild==NULL)
return1;
elsereturnNode(T->lchild)+Node(T-->rchild)+1;
elsereturn0;
}
intLeaf(BinTreeT)
{//算叶子数
if(T)
if(T->lchild==NULL)&&(T-->rchild==NULL)
return1;
elsereturnLeaf(T->lchild)+Node(T-->rchild);
elsereturn0;
}
⑻设图6-27所示的二叉树是森林F所对应的二叉树,请画出森林F。
答:
方法:
⑼设有一棵树,如图6-28所示。
①请分别用双亲表示法、孩子表示法、孩子兄弟表示法给出该树的存储结构。
②请给出该树的先序遍历序列和后序遍历序列。
③请将这棵树转换成二叉树。
答:
①双亲表示法:
孩子表示法:
孩子兄弟表示法:
②先序:
abdechkgmfn
后序:
debhkgcfnma
③
⑽设给定权值集合w={3,5,7,8,11,12},请构造关于w的一棵huffman树,并求其加权路径长度WPL。
答:
huffman树:
WPL=3*3+5*3+7*3+8*3+11*2+12*2=115
⑾假设用于通信的电文是由字符集{a,b,c,d,e,f,g,h}中的字符构成,这8个字符在电文中出现的概率分别为{,,,,,,,}。
①请画出对应的huffman树(按左子树根结点的权小于等于右子树根结点的权的次序构造)。
②求出每个字符的huffman编码。
答:
①
②
Huffman编码:
a:
0010b:
10c:
00000d:
0001
e:
01f:
00001g:
11h:
0011
3、求两个n阶方阵相加C=A+B的算法如下,分析其时间复杂度。
#defineMAX20/*定义最大的方阶*/
voidMatrixAdd(intn,intA[MAX][MAX],intB[MAX][MAX],intC[MAX][MAX])
{inti,j;
for(i=0;ifor(j=0;jC[i][j]=A[i][j]+B[i][j];
}
答:
因为C[i][j]=A[i][j]+B[i][j];这条语句执行的频率为n^2;
所以其时间复杂度为0(n^2)。
四、算法设计题
1、请描述队列和堆栈的特点,并设计一个算法实现:
用两个栈(栈A,栈B)实现一个队列,请描述入队与出队的过程。
答:
栈的特点是后进先出,队列的特点是先进先出。
所以,用两个栈A和B模拟一个队列时,A作输入栈,逐个元素压栈,以此模拟队列元素的入队。
当需要出队时,将栈A退栈并逐个压入栈B中,A中最先入栈的元素,在B中处于栈顶。
B退栈,相当于队列的出队,实现了先进先出。
显然,只有栈B为空且A也为空,才算是队列空。
[算法讨论]算法中假定栈s1和栈s2容量相同。
出队从栈s2出,当s2为空时,若s1不空,则将s1倒入s2再出栈。
入队在s1,当s1满后,若s2
空,则将s1倒入s2,之后再入队。
因此队列的容量为两栈容量之和。
元素从栈s1倒入s2,必须在s2空的情况下才能进行,即在要求出队操作时,若s2
空,则不论s1元素多少(只要不空),就要全部倒入s2中。
算法:
ElementTypeDeQueue(A)
{
if(Empty(A)
{
printf("Error!
");
exit(0);
}
else
returnPop(A);
}
voidEnQueue(A,ElementTypex)
{
ElementTypet;
while(!
Empty(A))
{
t=Pop(A);
Push(B,t);
}
Push(A,x);
while(!
Empty(B))
{
t=Pop(B);
Push(A,t);
}
2、已知长度为n的线性表A采用顺序存储结构,设计一个算法删除线性表A中所有值为key的数据元素。
答:
[题目分析]在顺序存储的线性表上删除元素通常要涉及到一系列元素的移动(删第i个元素第i+1至第n个元素要依次前移)本题要求删除线性表中所有值为key的数据元素并未要求元素间的相对位置不变,因此可以考虑设头尾两个指针(i=1,j=n)从两端向中间移动,凡遇到值item的数据元素时,直接将右端元素左移至值为key的数据元素位置。
具体实现如下:
voidDelete(ElemTypeA[]intn)
∥A是有n个元素的一维数组本算法删除A中所有值为item的元素
{
i=1;j=n;∥设置数组低、高端指针(下标)
while(i {
while(i=key)
i++;∥若值不为key左移指针
if(ij--;∥若右端元素值为key指针左移
if(iA[i++]=A[j--];
}
}
3、假设程序代码中包含三种符号:
圆括号()、方括号[]和大括号{},并且这些符号必须成对使用。
请问能否用栈来判断程序中以上符号是否正确配对?
若能,请分析判断方法,并写出算法代码。
答:
能,判断方法:
设置一个括号栈,扫描表达式:
遇到左括号(包括(、[和{)时进栈,遇到右括号时,若栈是相匹配的左括号,则出栈,否则,返回0。
若表达式扫描结束,栈为空,返回1表示括号正确匹配,否则返回0。
算法代码:
intcorrect(charexp[],intn)
{
charst[MaxSize];
inttop=-1,i=0,tag=1;
while(i{
if(exp[i]=='('||exp[i]=='['||exp[i]=='{')
/*遇到'('、'['或'{',则将其入栈*/
{
top++;
st[top]=exp[i];
}
if(exp[i]==‘)’)//遇到‘)’,若栈顶是‘(’,则继续处理,否则以不配对返回
if(st[top]=='(')
{
top--;
}
else
{
tag=0;
}
if(exp[i]==‘]’)//遇到‘]’,若栈顶是‘[’,则继续处理,否则以不配对返回
if(st[top]=='[')
{
top--;
}
else
{
tag=0;
}
if(exp[i]==‘}’)//遇到‘}’,若栈顶是‘{’,则继续处理,否则以不配对返回
if(st[top]=='{')
{
top--;
}
else
{
tag=0;
}
i++;
/*表达式扫描完毕*/
if(top>-1)
tag=0;/*若栈不空,则不配对*/
return(tag);
}