数据结构C语言版习题解答DOCWord格式.docx
- 文档编号:16273183
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:27
- 大小:237.86KB
数据结构C语言版习题解答DOCWord格式.docx
《数据结构C语言版习题解答DOCWord格式.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版习题解答DOCWord格式.docx(27页珍藏版)》请在冰豆网上搜索。
否则从后向前先移动
数据,找到合适的位置插入。
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;
}//lnsert_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;
ivj;
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;
j<
length;
j++){
if(L.EIem[j]==L.EIem[i]){
for(k=j;
k<
length-1;
k++){
L.Elem[k]=L.Elem[k+1];
length--;
//
j--;
//移动元素后,由于少了一个元素,因此要减1
}//endif
lf(L.EIem[j]>
L.EIem[i])break;
第二小问添加此句
}//endfor
}//endwhile
}//endfunctoion
2.8已知线性表L采用链式结构存放。
对两种不同情况分别写出算法,删除L中值相同的多余元素,使得L中没有重复元素:
(2)L中数据元素非递减有序排列。
(1)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->
next;
else{
p->
next=q;
}//else
}//while
p=p->
//开始后一结点的寻找
returnOK;
}//ListDelete
(2)L中数据元素非递减有序排列。
由于是有序的,遍历一次线性表就行了
StatusListDelete(LinkList&
L)
p=L->
next)
if(p->
data!
=q->
data){
//和第一问不同地方
}//if
else{
data==q->
//多个连续的重复值
next=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->
pa=pa->
//将当前最小结点插入A表表头
qa->
next=A->
A->
next=qa;
qb->
next=qb;
while(pa){
next=A->
while(pb){
pb=pb->
pb=B;
free(pb);
2.13设以带头结点的双向循环链表表示的线性表L=(a1,a2,a3,...,an)。
试写一
时间复杂度为0(n)的算法,将L改造为L=(ai,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指向最后一个偶数结点
pre;
//此时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输入完毕
while((e=getchar())!
@'
if(StackEmpty(s))
pop(s,c);
if(e!
=c)
if(!
StackEmpty(s))
//序列1元素还有剩余
return1;
}//lsReverse
3.7假设一个算术表达式中可以包含三种符号:
圆括号“(”和“)”、方括号“[”
和“]”、花括号“{”和“}”,且这三种括号可按任意次序嵌套使用。
编写判别给定表达式中所含的括号是否正确配对的算法(已知表达式已存入数据元素为字
符的顺序表中)。
算法:
StatusBracketTest(char*str)//判别表达式中三种括号是否匹配{
for(p=str;
*p;
p++)
if(*p=='
('
||*p==T||*p=='
{'
push(s,*p);
else
if(*P=='
)'
||*P=='
]'
}'
){
returnERROR;
if(*p=='
)'
c!
)if(*p==T&
['
)if(*p=='
}'
)}//if
}//for
StackEmpty(s))returnOK;
//必须与当前栈顶括号匹配
//进栈的符号还有剩余,Error
}//BracketTest
3.8设表达式由单字母变量、双目运算符和圆括号组成(如:
“(a*(b+c)-d)/e)”。
试写一个算法,将一个书写正确的表达式转换为逆波兰式。
1.遇到数字直接发送2.遇到’('
直接入栈3•遇到’)'
则将栈内元素发送直至遇到’(’4.栈空
则直接入栈5.栈非空时若优先级大于栈内则入栈,否则栈内元素出栈
intRankOfOperator(
charc){
switch
(c){
case
#'
:
return
+'
11.
-1;
0;
casecasecase}
1*1
/'
return2;
int
Precede(charc,charch){returnRankOfOperator(c)>
RankOfOperator(ch);
break;
default:
if(IsEmpty(s))
push(s,*exp);
suffix[i++]=pop(s);
exp--;
//与后面的exp++相抵消,使得栈内优先级大于等于栈外的都出栈
}//endswitch
}//endelseexp++;
while(!
lsEmpty(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;
data=value;
next=L.tail->
next=p;
L.tail=p;
void
if
DeparQueue(CycleListQueue&
L,DataType&
d){(L.tail->
next!
=L.tail->
Node*p=L.tail->
next=p->
d=p->
data;
if(p==L.tail)L.tail=p->
deletep;
假设将循环队列定义为:
以rear和length分别指示队尾元素和队列长度。
returnd;
3.11
试给出此循环队列的队满条件,并写出相应的入队和出队算法(在出队算法中要传递回队头元素的值)。
此循环队列的队满条件:
Q.length==MAXQSIZE;
入队算法:
StatusEnCyQueue(CyQueue&
Q,intx)//带length域的循环队列入队算法{
if(Q.length==MAXSIZE)returnOVERFLOW;
Q.rear=(Q.rea叶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设有一个准对角矩阵
ra11a12
a21a22
a33a34
a43a44
按以下方式存于一维数组B[4m]中:
a11
a12
a21
a22
a33
a34
a43
...
aij
a2m-1,2m
a2m,2m
6
k
4m-24m-1
012345
写出由一对下标(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。
故:
1)腐奇数k={
bni/为翩
5.5已知稀疏矩阵A4X5如下:
(1)用三元组表作为存储结构,绘出相应的三元组表示意图;
(2)用十字链表作为存储结构,绘出相应的十字链表示意图。
(1)三元组表:
i
j
v
1
2
5
4
7
(2)十字链表
214
<
¥
5|7
第六章数和二叉树
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=S(i-i)・ni+l
iz2
6.8已知一棵树如图6-1所示,画出与该树对应的二叉树,并写出该树的先根遍历序列和后根遍历序列。
先根遍历:
ABCEIJFGKHD后根遍历:
BIJEFKGHCDA对应的二叉树:
A
B
C
G
K
H
6.9将如图6-2所示的森林转化为对应的二叉树。
图6-2
森林对应的二叉树:
N
M
O
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树;
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(BitTree「Status(*Visit)(TEIemTypee)//层序遍历二叉树{
InitQueue(Q);
//初始化队列
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!
num+=CountLeaves(T->
firstchild);
num+=1;
//firstchild域为空,则为叶子结点
returnnum;
第七章图
请给出该图的
(1)
邻接矩阵示意图
⑵
邻接表示意图
⑶
逆邻接表
⑷
所有强连通分量
图7-1
(1)邻接矩阵
「0
L1
(2)邻接表
0」
v1
v2
v3
v4
v5
v6
(3)逆邻接表
□—HZlZ
(4)强连通分量
7.2已知图G的邻接矩阵如图7-2所示。
写出该图从顶点1出发的深度优先搜索序列和广度优先搜索序列,并画出相应的深度优先生成树和广度优先生成树。
12345678910
10
图7-2
深度优先序列:
17345621098
深度优先生
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 语言版 习题 解答 DOC