数据结构C语言版习题解答Word文档格式.docx
《数据结构C语言版习题解答Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版习题解答Word文档格式.docx(23页珍藏版)》请在冰豆网上搜索。
过程:
第二章
2.3已知顺序表La中数据元素按非递减有序排列。
试写一个算法,将元素x插到La的合适位置上,保持该表的有序性。
思路:
先判断线性表的存储空间是否满,若满返回Error;
否则从后向前先移动数据,找到合适的位置插入。
StatusInsert_SqList(SqList&
La,intx)//把x插入递增有序表La中
{
if(La.length==La.listsize)returnERROR;
for(i=La.length-1;
La.elem[i]>
x&
&
i>
=0;
i--)
La.elem[i+1]=La.elem[i];
La.elem[i+1]=x;
La.length++;
returnOK;
}//Insert_SqList
2.5试写一个算法,实现顺序表的就地逆置,即在原表的存储空间将线性表(a1,a2,...,an-1,an)逆置为(an,an-1,...,a2,a1)
//思路就是两个指示变量i,j同时分别从顺序表的开始和结尾处相向改变
voidreverse(SqList&
A)//顺序表的就地逆置
ElemTypep;
for(i=1,j=A.length;
j;
i++,j--)
//A.elem[i]<
->
A.elem[j];
p=A.elem[i];
A.elem[i[=A.elem[j];
A.elem[j]=p;
}//reverse
2.7已知线性表L采用顺序存储结构存放,对两种不同情况分别写出算法,删除L中多余的元素,使得L中没有重复元素:
(1)L中数据元素无序排列;
(2)L中数据元素非递减有序排列。
voidDelete_SameElem(SqLink&
L,intL.length){
//内层循环移动参数,中层循环寻找相同元,外层循环遍历整个表
inti=0;
intj=i+1;
intlength=L.length;
while(i<
length){
for(j=i+1;
length;
j++){
if(L.Elem[j]==L.Elem[i]){//
length-1;
k++){
L.Elem[k]=L.Elem[k+1];
length--;
j--;
//移动元素后,由于少了一个元素,因此要减1
}
}//endif
If(L.Elem[j]>
L.Elem[i])break;
//第二小问添加此句
}//endfor
}//endwhile
}//endfunctoion
2.8已知线性表L采用链式结构存放。
对两种不同情况分别写出算法,删除L中值相同的多余元素,使得L中没有重复元素:
由于是无序排列,需要线性表中每个元素都要相互进行比较。
StatusListDelete(Linklist&
L)//L是带头结点的线性表
ElemType*p,*q;
p==L->
next;
q=p->
//设定p变化较慢,q变化较快
while(p->
next){
while(q){
if(p->
data!
=q->
data)
q=q->
else{
p->
next=q;
}//else
}//while
p=p->
//开始后一结点的寻找
returnOK;
}//ListDelete
由于是有序的,遍历一次线性表就行了
StatusListDelete(LinkList&
L)
p=L->
next)
data){
//和第一问不同地方
}//if
data==q->
//多个连续的重复值
p=q;
//删除值重复的结点,并修改相应的指针
2.9设有两个非递减有序的单链表A,B。
请写出算法,将A和B就地归并成一个按元素值非递增有序的单链表。
//将合并逆置后的结果放在C表中,并删除B表
StatusListMergeOppose_L(LinkList&
A,LinkList&
B,LinkList&
C)
LinkListpa,pb,qa,qb;
pa=A;
pb=B;
qa=pa;
//保存pa的前驱指针
qb=pb;
//保存pb的前驱指针
pa=pa->
pb=pb->
A->
next=NULL;
C=A;
while(pa&
pb){
if(pa->
data<
pb->
qa=pa;
pa=pa->
qa->
next=A->
//将当前最小结点插入A表表头
A->
next=qa;
else{
qb=pb;
pb=pb->
qb->
next=qb;
}
while(pa){
qa=pa;
pa=pa->
qa->
A->
while(pb){
qb=pb;
pb=pb->
qb->
free(pb);
returnOK;
2.13设以带头结点的双向循环链表表示的线性表L=(a1,a2,a3,...,an)。
试写一时间复杂度为O(n)的算法,将L改造为L=(a1,a3,...,an,...,a4,a2)。
voidReform(DuLinkedList&
L)//按1,3,5,...4,2的顺序重排双向循环链表L中的所有结点
p=L.next;
next!
=L&
next->
=L)
next=p->
}//p指向最后一个奇数结点
next==L)//结点个数是奇数,使最后一个奇数结点next指向最后一个偶数结点
next=L->
pre->
pre;
else//结点个数是偶数,使最后一个奇数结点next指向最后一个偶数结点
//此时p指向最后一个偶数结点
pre!
next=L;
//最后一个结点next指向头结点
//调整了next链的结构,此时pre链仍为原状
//调整pre链的结构
for(p=L;
=L;
next)p->
pre=p;
L->
//头结点的pre指向a2结点
}//Reform
第三章栈和队列
3.6试写一个算法,识别依次读入的一个以@为结束符的字符序列是否为形如“序列1&
序列2”模式的字符序列。
其中,序列1和序列2中都不包含字符‘&
’,且序列2是序列1的逆序。
例如,“a+b&
b+a”是属于该模式的字符序列,而“1+3&
3-1”则不是。
算法:
intSeqReverse()//判断输入的字符串中'
'
前和'
后部分是否为逆串,是则返回1,否则返回0
InitStack(s);
while((e=getchar())!
='
)
if(e==’@’)
return0;
//不允许在’&
’之前出现’@’
push(s,e);
}//序列1输入完毕
@'
if(StackEmpty(s))
pop(s,c);
if(e!
=c)
if(!
StackEmpty(s))
//序列1元素还有剩余
return1;
}//IsReverse
3.7假设一个算术表达式中可以包含三种符号:
圆括号“(”和“)”、方括号“[”和“]”、花括号“{”和“}”,且这三种括号可按任意次序嵌套使用。
编写判别给定表达式中所含的括号是否正确配对的算法(已知表达式已存入数据元素为字符的顺序表中)。
StatusBracketTest(char*str)//判别表达式中三种括号是否匹配
for(p=str;
*p;
p++)
if(*p=='
('
||*p=='
['
{'
push(s,*p);
else
)'
]'
}'
returnERROR;
c!
)returnERROR;
//必须与当前栈顶括号匹配
}//for
StackEmpty(s))returnERROR;
//进栈的符号还有剩余,Error
}//BracketTest
3.8设表达式由单字母变量、双目运算符和圆括号组成(如:
“(a*(b+c)-d)/e)”。
试写一个算法,将一个书写正确的表达式转换为逆波兰式。
1.遇到数字直接发送2.遇到’(’直接入栈3.遇到’)’则将栈内元素发送直至遇到’(’4.栈空则直接入栈5.栈非空时若优先级大于栈内则入栈,否则栈内元素出栈
intRankOfOperator(charc){
switch(c){
case'
#'
:
return-1;
+'
-'
*'
/'
return2;
intPrecede(charc,charch){
returnRankOfOperator(c)>
RankOfOperator(ch);
voidExpressionTOPolandStyle(charsuffix[],char*exp){
Stacks;
InitStack(s,100);
inti=0;
charc;
while(*exp){
if(isdigital(*exp))
suffix[i++]=*exp;
switch(*exp){
case'
push(s,'
);
while((c=pops(s))!
suffix[i++]=c;
break;
default:
if(IsEmpty(s))
push(s,*exp);
else{
suffix[i++]=pop(s);
exp--;
//与后面的exp++相抵消,使得栈内优先级大于等于栈外的都出栈
}
}//endswitch
}//endelse
exp++;
while(!
IsEmpty(s))suffix[i++]=pop(s);
suffix[i]=0;
3.10假设以带头结点的单循环链表表示队列,只设一个尾指针指向队尾元素,不设头指针。
试编写相应的队列初始化、入队和出队算法(在出队算法中要传回队头元素的值)
要点:
定义好数据类型,带头结点的单循环链表,只有尾指针,注意删除元素时只有一个元素的特殊性
typedefintDataType
structNode{
DataTypedata;
Node*next;
};
structCycleListQueue{
Node*tail;
voidInitCycleListQueue(CycleListQueue&
L){
L.tail=newNode;
L.tail->
next=L.tail;
voidEnterQueue(CycleListQueue&
L,DataTypevalue){
Node*p=newNode;
p->
data=value;
next=L.tail->
L.tail->
next=p;
L.tail=p;
voidDeparQueue(CycleListQueue&
L,DataType&
d){
if(L.tail->
=L.tail->
Node*p=L.tail->
L.tail->
d=p->
data;
if(p==L.tail)L.tail=p->
deletep;
returnd;
3.11假设将循环队列定义为:
以rear和length分别指示队尾元素和队列长度。
试给出此循环队列的队满条件,并写出相应的入队和出队算法(在出队算法中要传递回队头元素的值)。
此循环队列的队满条件:
Q.length==MAXQSIZE;
入队算法:
StatusEnCyQueue(CyQueue&
Q,intx)//带length域的循环队列入队算法
if(Q.length==MAXSIZE)returnOVERFLOW;
Q.rear=(Q.rear+1)%MAXSIZE;
Q.base[Q.rear]=x;
//rear指向队尾元素
Q.length++;
}//EnCyQueue
出队算法:
StatusDeCyQueue(CyQueue&
Q,int&
x)//带length域的循环队列出队算法,用x返回队头元素的值
if(Q.length==0)returnError;
//空队列,错误
head=(Q.rear-Q.length+1)%MAXSIZE;
//head指向队头
x=Q.base[head];
Q.length--;
}//DeCyQueue
3.12试写一个算法:
判别读入的一个以‘@’为结束符的字符序列是否是“回文”(所谓“回文”是指正读和反读都相同的字符序列,如“xxyzyxx”是回文,而“abcab”则不是回文)。
StatusTest()//判别输入的字符串是否回文序列,是则返回1,否则返回0
InitStack(S);
InitQueue(Q);
while((c=getchar())!
Push(S,c);
EnQueue(Q,c);
//同时使用栈和队列两种结构
while(!
StackEmpty(S))
Pop(S,a);
DeQueue(Q,b);
if(a!
=b)returnERROR;
}//Test
第五章多维数组
5.4设有一个准对角矩阵
按以下方式存于一维数组B[4m]中:
1
2
3
4
5
6
k
4m-2
4m-1
a11
a12
a21
a22
a33
a34
a43
...
aij
a2m-1,2m
a2m,2m
写出由一对下标(i,j)求k的转换公式。
因为i行前有2(i-1)个元素。
现考虑i行情况,当j是奇数,i行有1个元素,k=2(i-1)+1-1=2(i-1);
否则i行有2个元素,k=2(i-1)+2-1=2i-1。
故:
k=
或若i为奇数,k=2(i-1)+j-i=i+j-2;
当i为偶数时,k=2i-(i-j)-1=i+j-1
5.5已知稀疏矩阵A4×
5如下:
(1)用三元组表作为存储结构,绘出相应的三元组表示意图;
(2)用十字链表作为存储结构,绘出相应的十字链表示意图。
(1)三元组表:
i
j
v
7
(2)十字链表
第六章数和二叉树
6.5已知一棵度为k的树中有n1个度为1的结点,n2个度为2的结点,...,nk个度为k的结点,问该树中有多少个叶子结点?
设叶子结点有x个,则树的结点总数为n1+n2+…nk+x;
同时除了根结点外,每个结点都指向一个结点,所有从这个角度考虑树的结点总数为:
n1+2?
n2+…k?
nk+1;
n1+n2+…nk+x=n1+2?
nk+1,可得x=
6.8已知一棵树如图6-1所示,画出与该树对应的二叉树,并写出该树的先根遍历序列和后根遍历序列。
先根遍历:
ABCEIJFGKHD
后根遍历:
BIJEFKGHCDA
对应的二叉树:
6.9将如图6-2所示的森林转化为对应的二叉树。
树对应的二叉树
森林对应的二叉树:
6.11已知某二叉树的中序序列为DCBGEAHFIJK,后序序列为DCEGBFHKJIA。
请画出该二叉树。
6.14假设某个电文由(a,b,c,d,e,f,g,h)8个字母组成,每个字母在电文中出现的次数分别为(7,19,2,6,32,3,21,10),试解答下列问题:
(1)画出出huffman树;
(2)写出每个字母的huffman编码;
a:
1010b:
00c:
10000d:
1001e:
11f:
10001g:
01h:
1011
(3)在对该电文进行最优二进制编码处理后,电文的二进制位数。
4*7+2*19+5*2+4*6+2*32+5*3+2*21+4*10=261
6.17写出按层次遍历二叉树的算法。
用队列存储结构,并用递归方法
StatusLevelOrderTraverse(BitTreeT,Status(*Visit)(TElemTypee)//层序遍历二叉树
//初始化队列
T)returnError;
//空树,直接返回
EnQueue(Q,T);
//根结点入队
BiTNode*p;
QueueEmpty(Q))
DeQueue(Q,p);
Visit(p->
data);
lchild)EnQueue(Q,p->
lchild);
rchild)EnQueue(Q,p->
rchild);
returnOk;
}//LevelOrderTraverse
6.19写出判断两棵给定二叉树是否相似的算法。
(注:
两棵二叉树B1和B2相似是指:
B1和B2皆空,或者皆不空且B1的左、右子树和B2的左、右子树分别相似。
采用递归进行比较判断
boolBiTreeSimilar(BiTreeT1,BiTreeT2)
if(T1==Null&
T2==Null)
elseif(T1==Null||T2==Null)
return(BiTreeSilimar(T1->
lchild,T2->
lchild)&
BiTreeSimilar(T1->
rchild,T2->
rchild));
6.21写出统计树中叶子结点个数的算法,树用孩子兄弟链表表示。
在孩子兄弟链表中,若结点的firstchild为Null,则为叶子结点;
采用递归方法。
intCountLeaves(TreeT,int&
num)//num传递的初值为0
if(T->
nextsibling!
=Null)
num+=CountLeaves(T->
nextsibling);
firstchild!
firstchild);
num+=1;
//firstchild域为空,则为叶子结点
returnnum;
第七章图
7.1已知有向图如图7-1所示,
请给出该图的
(1)邻接矩阵示意图
(2)邻接表示意图
(3)逆邻接表
(4)所有强连通分量
(1)邻接矩阵
(2)邻接表
(4)强连通分量
7.2已知图G的邻接矩阵如图7-2所示。
写出该图从顶点1出发的深度优先搜索序列和广度优先搜索序列,并画出相应的深度优先生成树和广度优先生成树。
8
9
10
图7-2
深度优先序列:
173********
深度优先生成树:
广度优先序列:
17931054862
广度优先生成树:
9.1若对大