数据结构 习题参考答案.docx
《数据结构 习题参考答案.docx》由会员分享,可在线阅读,更多相关《数据结构 习题参考答案.docx(19页珍藏版)》请在冰豆网上搜索。
数据结构习题参考答案
第1章
一、1~5:
BCCDC6~10:
ABABC11~15:
BBDCB16~17:
AD
二、1.数据的逻辑结构,数据的存储结构,数据的运算及实现;2.集合结构,线性结构,树形结构,图形结构;3.规模;4.抽象数据类型;5.顺序存储结构,索引存储结构,散列存储结构;6.时间复杂度;7.顺序存储,链式存储;8.插入,删除,定位
三、简答题
1.略;2.略;3.⑴O(n),⑵O
(1),⑶O(n2),⑷O(n),⑸O(n3),⑹O(n)
4.
第2章
一、1~5:
BBBDB6~10:
BAAAA11~13:
ABB
二、1.顺序,链式;2.前驱,后继;3.顺序表,链表;4.随机存取,空间利用率高;5.插入,删除;6.(n+1)/2,元素的插入位置;7.O
(1),随机存取;8.使空表和非空表的算法一致;9.也,不一定;10.链式,顺序;11.单向链表,双向链表,循环链表;12.p的前驱,O(n);13.表头指针
三、问答题(略)
四、算法及程序设计题
1.[解答]:
算法分两步执行,首先在单链表中找到值为x的结点*p和它的直接前驱结点*q,然后再删除直接前驱结点*q即可。
删除时,可将*p结点的数据域的值赋给*q结点,然后将*p结点删除。
typedefstructNode
{ElemTypedata;
structNode*next;
}LNode;
voidListDelete_Link(LNode*L,intx)//L是带头结点的单链表
{LNode*p,*q;intj;
q=L;p=L->next;j=0;
while(p&&p->data!
=x)//查找数据域值为x的结点
{q=p;j++;p=p->next;}
if(p==NULL){printf("x不在L中");return;}//查找失败
if(j==0){printf("x是第一个结点,它没有前驱");return;}//无前驱
q->data=x;//将p的值存入q中
q->next=p->next;//删除的是结点p
free(p);
}//ListDelete_Link
2.[解答]:
本题是遍历通过该链表的每个结点,每遇到一个结点,结点个数加1,结点个数存储在变量n中。
voidCount(LNode*head)
{LNode*p;intn=0;
p=head->next;
while(p!
=NULL)
{if(p->data==x)n++;
p=p->next;
}
return(n);
}//Count
3.[解答]:
本题算法的思想是先建立一个待插入的结点,然后依次与链表中的各结点的数据域比较大小,找到插入该结点的位置,最后插入该结点。
LNode*OrderListInsert_Link(LNode*head,intx)
{LNode*t,*p,*q;
t=(LNode*)malloc(sizeof(LNode));//建立一个待插入的结点
t->data=x;t->next=NULL;
q=head;p=head->next;
while(p&&x>p->data){q=p;p=p->next;}//查找插入位置
t->next=p;q->next=t;//将t结点插入到q和p之间
return(head);
}//OrderListInsert_Link
第3章
一、1~5:
DDDBA6~10:
CACCC11~15:
ABDCA16~17:
CC
二、1.O(n),O
(1),O
(1),O(n);2.线性,任何,栈顶,队尾,队首;3.不可能;4.先进后出;
5.先进先出;
三、应用题
1.14种出栈序列:
ABCD,ABDC,ACBD,ACDB,ADCB,BACD,BADC,BCAD,BCDA,BDCA,CBAD,
CBDA,CDBA,DCBA
2.略
四、算法及程序设计题
1.[解答]
#include
#defineMAXSIZE50
typedefstruct
{chardatas[MAXSIZE];
inttop;
}SqStack;
SqStack*s;
voidreverse(SqStack*p,intflag)//将输入的数据序列用递归方法逆置输出
{charch;
if(flag)
{ch=getchar();
if(ch!
='@')
{p->datas[++p->top]=ch;flag=1;}
elseflag=0;}
else
{ch=p->datas[p->top--];printf("%c,",ch);
flag=0;}
if(p->top>=0)reverse(p,flag);//如果不是结束符号@则递归
}
main()
{intflag1=1;
s->top=-1;
printf("pleaseinputvalue:
\n");
reverse(s,flag1);
}
2.[解答]本题是对一个循环链队列做插入和删除运算,假设不需要保留被删除结点的值和不需要回收结点,可将算法描述如下:
(1)入队
voidEnLinkQueue(QNode*q,ElemTypex)
{LinkQList*rear,*p;
p=(QNode*)malloc(sizeof(QNode));
if(rear==NULL)
{rear=p;rear->next=p);}//链接成循环链表
else
{p->next=rear->next;rear->next=p;rear=p;}
//若条件成立,则建立循环链队列的第一个结点,否则在队尾插入*p结点
}//EnLinkQueue
(2)出队
voidDeLinkQueue(QNode*q)
{LinkQList*rear;
if(rear==NULL)printf("underflow\n");
if(rear->next==rear)rear=NULL;
elserear->next=rear->next->next;
//rear->next指向的结点为循环链队列的队头结点
}//DeLinkQueue
3.[解答]此算法中包括栈初始化操作,读入字符,压栈和出栈等操作。
typedefstructSNode
{chardata;
structSNode*next;
}SNode,*LinkStack;
voidMatcher(SNode*ls)
{SNode*p;charch,c;
while((ch=getchar())!
='\n')
if(ch=='('||ch=='['||ch='{')
{p=(SNode*)malloc(sizeof(SNode));
p->data=ch;p->next=ls;ls=p;}
else{p=ls;c=p->data;ls=ls->next;free(p);}
if(!
((c=='('&&ch==')')||(c=='['&&ch==']')||(c=='{'&&ch=='}')))
return(0);
return
(1);
}//Matcher
第4章
一、1~5:
DDCCD
二、1.顺序定长存储方式,堆分配存储方式;2.两个串的长度相等且对应位置的字符相同;
3.零个字符的串,零;4.由一个或多个空格字符组成的串,其包含的空格个数;5.14;6.GOOD└┙BYE!
;7.3,CDE;8.13,studentteacher,I’m;
三、问答题(略)
四、算法及程序设计题
1.voidSearch(LinkStringx,LinkStringy)
{p=x->next;
while(p!
=NULL)
{q=y->next;
while(q!
=NULL)
if(p->data==q->data)q=q->next;
elsereturn("该字符不在y串中");
p=p->next};
if(p==NULL)return("串x中的字符全都在串y中");
}//Search
2.[解答]:
在串S中找到最先出现的子串"ab",p指向data域值为'a'的结点,其后为data域值为'b'的结点。
将它们的data域值分别改为'x’和'z’,再创建一个data域值为'y'的结点,将其插入到*p之后。
voidRepl(LinkStringS)
{LinkString*p=S->next,*q;
intfind=0;
while(p->next!
=NULL&&find==0)
{if(p->data=='a'&&p->next->data=='b')
{p->data='x';p->next->data='z';
q=(LinkString*)malloc(sizeof(LinkString));
q->data='y';q->next=p->next;p->next=q;
find=1;}
elsep=p->next;}
}//Rep1
第5章
一、1~5:
CBCBA6~10:
ADDCA
二、1.Loc(a00)+(i*n+j)*k;2.行优先存储,列优先存储;3.稀疏矩阵;4.1060;5.压缩矩阵;6.1168;7.第一个元素,子表;8.下三角,n(n+1)/2;9.y,()
三、简答题(略)四、算法设计题(略)
第6章
一、1.B(二叉树并非是树的特殊情形,尽管两者有许多相同之处,但是它们是两种不同的数据结构);2.D;3.C;4.C;5.B;6.C;7.D;8.C;9.D;10.A;11.C;12.D
二、1.
2i,2i+1;2.4;3.33;4.后面;5.中根,先根;6.12,5,7;7.68;8.遍历;9.线索化;10.完全二叉树,哈夫曼树;11.结点的度;12.深度;13.32;14.中序序列;15.13,3
三、应用题
1.哈夫曼树为:
2.构造的哈夫曼树为:
带权路径长度为:
WPL=(3+4+5+6)×2=36
3.先序遍历序列为:
ABCDGEIHFK
4.①该顺序存储结构对应的二叉树为:
②前序遍历结果:
EADCBJFGHI
中序遍历结果:
ABCDJEFHGI
后序遍历结果:
BCJDAHIGFE
③G的父结点为:
F;左右孩子为:
H,I;度为2。
④由二叉树还原的森林如下所示:
四、算法与程序设计题
1.voidinorder(BTNode*T)
{BTNode*p,*s[MAXSIZE];
inttop=0;p=T;
while(p||top>0){
while(p)
{s[++top]=p;p=p->lchild;}
if(top>0)
{p=s[top--];
printf(p->data);
p=p->rchild;}
}
}
2.voidcount(BTNode*T,int*s)
{if(T!
=NULL)
{if(T->lchild&&T->rchild)*s++;
count(T->lchild,s);
count(T->rchild,s);
}
}
第7章
一、选择题
1~5:
CDCBA6~10:
ADDCB11~15:
BBDBC16~20:
BDACC
二、填空题
1.邻接矩阵;2.存在环路的图;3.n+2e;4.n-1;5.邻接表;6.邻接矩阵、邻接表;7.前序
三、应用题
1.⑴各顶点的入度和出度为:
⑵图中有8条弧⑶邻接矩阵与邻接表如下所示
顶点
入度
出度
v0
2
0
v1
3
1
v2
2
2
v3
0
3
v4
1
2
2.用Prim算法从顶点1开始求最小生成树的过程如下所示:
用Prim算法求最小生成树,在寻找下一条最小边时,需要扫描未并入的所有顶点,每并入一个顶点就要做一次全面扫描,故时间复杂度为O(n2)。
3.按深度优先搜索遍历得到的顶点序列:
0,1,2,8,5,6,7,9,4,3
按广度优先搜索遍历得到的顶点序列:
0,1,4,2,6,3,8,5,7,9
4.按照Kruskal算法网的最小生成树的产生过程如下:
5.
由上述求解过程可知,从v0到其余各顶点的最短路径为:
路径
长度
v0,v2
10
v0,v4
30
v0,v4,v3
50
v0,v4,v3,v5
60
v1
∞
6.
(1)各事件的最早发生时间ve和最迟发生时间vl为:
事件
v1
v2
v3
v4
v5
v6
v7
v8
v9
v10
v11
Ve
0
3
4
5
7
9
15
11
21
22
28
vl
0
6
4
15
7
19
21
11
21
22
28
(2)各活动的最早开始时间e和最迟开始时间l为:
活动
a1
a2
a3
a4
a5
a6
a7
a8
a9
a10
a11
a12
a13
a14
a15
e
0
0
3
3
4
4
5
7
7
9
15
11
11
21
22
l
3
0
13
6
4
14
15
13
7
19
21
18
11
21
22
由此可以看出关键活动有:
a2,a5,a9,a13,a14,a15,因此关键路径为:
(v1,v3,v5,v8,v9,v10,v11)。
四、(略)
第8章
一、1~5:
BCCDC6~10:
DBBBA
二、1.1,2,4,log2n;2.索引表,主表,和;3.越大,越小,4.顺序,有序,顺序或链式存储;5.13/2,(log213)-1
三、应用题
1.解:
顺序查找:
ASL=(n+1)/2=13
折半查找:
ASL=(1*1+2*2+4*3+8*4+9*5+1*6)/25=100/25=4
分块查找:
ASL=((2+3+4+5+6)+(3+4+5+6+7)+(4+5+6+7+8)+(5+6+7+8+9+)+(6+7+8+9+10))/25=150/25=6
2.解:
计算散列地址:
H(19)=19%13=6;H(01)=01%13=1;H(23)=23%13=10;
H(14)=14%13=1(冲突),H1=(1+12)%19=2;
H(55)=55%13=3;H(20)=20%13=7;
H(84)=84%13=6(冲突),H1=(6+12)%19=7(冲突),H2=(6-12)%19=5;
H(27)=27%13=1(冲突),H1=(1+12)%19=2(冲突),H2=(1-12)%19=0;
H(68)=68%13=3(冲突),H1=(3+12)%19=4;
H(11)=11%13=11;
H(10)=10%13=10(冲突),H1=(10+12)%19=11(冲突),H2=(10-12)%19=9;
H(77)=77%13=12。
散列表为:
0
1
2
3
4
5
6
7
8
9
10-
11
12
13
14
15
16
17
18
27
01
14
55
68
84
19
20
10
23
11
77
3.解:
计算散列地址:
H(32)=32%13=6;H(75)=75%13=10;H(29)=29%13=3;H(63)=63%13=11;H(48)=48%13=9;
H(94)=94%13=3(冲突),H1=(3+1)%13=4;H(25)=25%13=12;
H(36)=36%13=10(冲突),H1=(10+1)%13=11(冲突),H2=(10+2)%13=12(冲突),H3=(10+3)%13=0;
H(18)=18%13=5;H(70)=70%13=5(冲突),H1=(5+1)%13=6(冲突),H2=(5+2)%13=7;
散列表为:
地址
0
1
2
3
4
5
6
7
8
9
10
11
12
关键字
36
29
94
18
32
70
48
75
63
25
查找成功的平均查找长度:
ASL=(7*1+1*2+1*3+1*4)/10=16/10=1.6
查找失败的平均查找长度:
ASL=(2+1+1+6+5+4+3+2+1+5+4+3+2)/13=3
四、算法题
1.解:
intBinSearch(ListSqL,intlow,inthigh,keytypeK)
{while(low<=high)
{intmid=(low+high)/2;//求出待查区间中间点元素下标
if(K==L.e[mid].key)returnmid;//查找成功返回元素下标
elseif(Khigh=mid-1;//在左子表上继续查找
elselow=mid+1;//在右子表上继续查找
}
return-1;//查找失败返回-1
}
2.解:
structElemtype//数据元素的数据类型定义
{keytypekey;//关键字项
};
structLnode
{ElemTypedata;
structLnode*next;
};
intseqsearch(Lnode*L,keytypes)
{Lnode*p=L->next;
intn=1;
while(p&&(p->data.key!
=s))
{p=p->next;n++;}
if(p)returnn;
elsereturn–1;
}
3.解
voidlevel(BSTreeroot,p)
{intlevel=0;
if(!
root)return(0);
else
{Level++;
while(root->key!
=p->key)
{if(p->keykey)
root=root->lchild;
elseroot=root->rchild;
}
return(level);
}
}
第9章
一、选择题
BBBCCCCBAC
二、填空题
1.直接插入排序,直接选择排序;2.5,4,8;3.快速排序,归并排序,希尔排序,选择排序,快速排序,堆排序;4.n-1,从小到大排列,从大到小排列,n(n-1)/2;5.3
三、应用题
1.稳定的排序算法有直接插入排序、折半插入排序、冒泡排序、归并排序和基数排序。
不稳定的排序算法有希尔排序、直接选择排序、堆排序、快速排序。
2.插入20的过程:
139>20:
high=mid-1=3;low<=high;mid=(low+high)/2=4/2=2
213<20:
low=mid+1=3;low>high;查找过程结束,插入位置为3。
最终结果为:
613202839417285
(1)插入排序所要进行的比较次数与待排序的记录的初始状态有关。
若初始状态基本有序,每次查找时都会搜索到有序表的最后一个元素才找到插入位置。
若每次插入的元素在有序表中的插入位置靠中间,则查找次数最少。
(2)在一些特殊情况下,二分法插入排序比直接插入排序要执行更多的比较。
这句话是对的。
若初始状态基本有序,则折半插入排序,每次查找时都会搜索到有序表的最后一个元素才找到插入位置。
直接插入排序则每次只比较一次就找到合适位置。
3.答:
因排序的元素个数很大,所以需要采用排序速度较快的排序方法。
排序速度比较快的排序方法有快速排序、堆排序、归并排序和基数排序等。
其中快速排序、归并排序和基数排序都是在排序结束后才能确定数据元素的全部序列,而排序过程中无法知道部分连续位置上的最终元素。
但堆排序则每次输出一个堆顶元素(即最大或最小元素),然后对堆进行再调整,保证堆顶元素总是剩下元素的最大或最小的,从而可知,若在大量数据的文件中,只选取排序后的前几名,采用堆排序最合适。
4.
(1)100,85,95,75,80,60,82,40,20,10,65;是堆。
(2)100,95,85,82,80,75,65,60,40,20,10;是堆。
(3)100,85,40,75,80,60,65,95,82,10,20;不是堆
调整以后的堆为:
100,95,65,85,80,60,40,75,82,10,20
(4)10,20,40,60,65,75,80,82,85,95,100;是堆。
四、算法题
1.假设待排序序列以单链表的形式存储,头指针为head,编写选择排序算法。
#include
structRtype
{KeyTypekey;//关键字域
};
structLnode
{Elemtypedata;
structLnode*next;
};
voidselectsort(Lnode*L)
{Lnode*p,*q,*r;
Rtypetemp;
for(p=L->next;p->next!
=NULL;p=p->next)
{q=p;
for(r=p->next;r!
=NULL;r=r->next)
if(q->data>r->data)q=r;
if(p!
=q)
{temp=p->data;p-.data=q->data;q->data=temp;}
}
}
2.设计一个双向冒泡排序算法,即在排序过程中交替改变扫描方向。
structRtype
{KeyTypekey;//关键字域
};
structListSq
{Rtypee[MAXSIZE];//0号单元空闲,元素从1号单元开始存放
intlen;
}
voiddbubblesort(ListSqr,intn)
{inti,j,flag;
Rtypetemp;
flag=1;i=0;
while(flag)
{flag=0;
for(j=n-i;j
{if(r.e[j].key{flag=a;
temp=r.e[j];r.e[j]=r.e[j-1];r.e[j-1]=temp;}
}
for(j=i;j{if