您的当前位置:首页正文

数据结构习题课第8、7、6章(网上的答案有些有问题的)

来源:一二三四网
第8章 图

8。2 对于如图8.33 所示的无向图,试给出: (1)图中每个顶点的度; (2)该图的邻接矩阵; (3)该图的邻接表; (4)该图的连通分量.

(1) D(V0)=2;D(V1)=2;D(V2)=3;D(V3)=3;D(V4)=2;D(V5)=1; D(V6)=1。

0101000010100010100001010000010110001011001010100(2)邻接矩阵1010100

001100000110000000001000000100000100000010vV(3)邻接表

(4)连通分量 1:

2:

8.5 图8.35 所示的是某个无向图的邻接表,试: (1)画出此图;

(2)写出从顶点A 开始的DFS 遍历结果; (3)写出从顶点A 开始的BFS 遍历结果。

(1)图8。35 邻接表对应的无向图如图8。35.1 所示

(2)

从顶点A 开始的DFS 遍历,深度优先遍历的基本思想:对于给定的图 G=(V,E),首先将V中每一个顶点都标记为未被访问,然后,选取一个源点vV将v标记为被访问,再递归地用深度优先搜索方法,依次搜索v的所有邻接点w。若w未曾访问过,则以w为新的出发点继续深度优先搜索遍历,如果从v出发所有路的顶点都已被访问过,则结束. A,B,C,F,E,G,D

从顶点A 开始的BFS 遍历,基本思想:对于给定的图G=(V,E),从图中某未访问过的顶点vi出发: 1)访问顶点vi;

2)访问 vi 的所有未被访问的邻接点w1 ,w2 , …wk ;

3)依次从这些邻接点出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问; A,B,C,D,F,E,G

8.8 对如图8.36 所示的连通图,分别用Prim 和Kruskal算法构造其最小生成树。

解:(1)Prime 算法的基本思路、步骤P167 Prim算法的基本步骤如下:

(1)初始化:U={u0},TREE={}; (2)如果U=V(G),则输出最小生成树T,并结束算法;

(3)在所有两栖边中找一条权最小的边(u,v)(若候选两栖边中的最小边不止一条,可任选其中的一条),将边(u,v)加入到边集TREE中,并将顶点v并入集合U中.

(4)由于新顶点的加入,U的状态发生变化,需要对U与V—U之间的两栖边进行调整。

(5)转步骤(2)

Prim算法构造最小生成树过程:

(2)采用Kruskal 算法求解最小生成树时首先要对边进行由小到大进行排序,本题对边进行排序的结果是:(D,F)1、(C,F)2、(A,F)3、(A,C)4、(F,G)4、(D,E)4、(D,B)4、(C,D)5、(E,G)5、(A,D)6、(D,G)6、(A,B)7 。根据Kruskal 算法,构造最小生成树的过程如图

8。9 对于如图8。37 所示的有向网,用Dijkstra 方法求从顶点A 到图中其他顶点的最短路径,并写出执行算法过程中距离向量d 与路径向量p 的状态变化情况。

解:

Dijkstra算法的基本思想: 把图中所有顶点分成两组,第一组包括已确定最短路径的顶点,初始时只含有一个源点,记为集合S;第二组包括尚未确定最短路径的顶点,记为V—S。按最短路径长度递增的顺序逐个把V-S中的顶点加到S中去,直至从v0出发可以到达的所有顶点都包括到S中。在这个过程中,总保持从v0到第一组(S)各顶点的最短路径都不大于从v0到第二组(V—S)的任何顶点的最短路径长度,第二组的顶点对应的距离值是从v0到此顶点的只包括第一组(S)的顶点为中间顶点的最短路径长度.对于S中任意一点j,v0到j的路径长度皆小于v0到(V—S)中任意一点的路径长度。

(后面四行需要在集合S加上E)

从表中可以看出源点A 到其它各顶点的最短距离及路径为: A→B:48 路径:A→B

A→C:57 路径:A→D→F→C A→D:15 路径:A→D A→E:28 路径:A→E A→F:48 路径:A→D→F A→G:38 路径:A→D→G

8。10 试写出如图8.38 所示的AOV 网的4 个不同的拓扑序列。

(这里也有点问题,等待老师再次讲解) 解:拓扑排序过程:

1) 输入AOV网络。令 n 为顶点个数。

2) 在AOV网络中选一个没有直接前驱(入度为0)的顶点, 并输出之; 3) 从图中删去该顶点, 同时删去所有它发出的有向 边; 4) 重复以上(2)、(3)步, 直到

全部顶点均已输出,拓扑有序序列形成,拓扑排序完成; 图8.38 所示的AOV 网的4 个不同的拓扑序列为: (1)ABDCEFGIH (2)ABDECFGIH (3)DABCEFGIH (4)DAECBFGIH

8.11 计算如图8。39 所示的AOE 网中各顶点所表示的事件的发生时间ve(j),vl(j),各边所表示的活动的开始时间e(i),l(i),并找出其关键路径。

解: (1):e(i):表示活动ai的最早开始时间。 l(i):表示活动最迟开始时间的向量。 关键活动特征:e(i)=l(i)

l(j)—e(j)的值表示完成活动aj的时间余量,提前完成非关键活动并不能提高整个工程的进度。

事件可能的最早开始时间ve(i):对于某一事件vi,它可能的最早发生时间 事件允许的最晚发生时间vl(i):对于某一事件vi,它允许的最晚发生时间是在保证按时完成整个工程的前提下,该事件最晚必须发生的时间

可以得出:

第7章 二叉树

7.1 选择题.

(1)前序遍历和中序遍历结果相同的二叉树为( F );前序遍历和后序遍历结果相同的二叉树为( B ).

A.一般二叉树 B.只有根结点的二叉树

C.根结点无左孩子的二叉树 D.根结点无右孩子的二叉树

E.所有结点只有左子树的二叉树 F.所有结点只有右子树的二叉树. (2)以下有关二叉树的说法正确的是( B )。

A.二叉树的度为2 B.一棵二叉树的度可以小于2

C.二叉树中至少有一个结点的度为2 D.二叉树中任一个结点的度均为2 (3)一棵完全二叉树上有1001 个结点,其中叶子结点的个数为( D )。 A.250 B.500 C.254 D.501

注:1023为深度是10的满二叉树,有512个叶子结点,1001比1023少22个节点.所以有512—22+22/2=501片叶子

(4)一棵完全二叉树有999 个结点,它的深度为( B ). A.9 B.10 C.11 D.12

(5)一棵具有5 层的满二叉树所包含的结点个数为( B )。 A.15 B.31 C.63 D.32

7。2 用一维数组存放完全二叉树:ABCDEFGHI,则后序遍历该二叉树的结点序列为( HIDEBFGCA ).

7。10 已知一棵二叉树的中序遍历的结果为ABCEFGHD , 后序遍历的结果为 ABFHGEDC,试画出此二叉树。 解:

7。11 已知一棵二叉树的前序遍历的结果为ABCDEF,中序遍历的结果为CBAEDF,试画出此二叉树 解:

7。14 试编写一个函数,将一棵给定二叉树中所有结点的左、右子女互换。 解:

#include ”bintree。h\" void change(bintree t) { bintree p; if (t) {

p=t—〉lchild;

t—>lchild=t—〉rchild; t—〉rchild=p;

change(t—>lchild); change(t—>rchild); }

int main() { bintree t;

creat(&t); /*建立二叉树t 的存储结构*/ preorder(t); change(t); printf(”\\n\"); preorder(t); }

7。18 假设二叉树采用链式方式存储,root 为其根结点,p 指向二叉树中的任意一个结点,编写一个求从根结点到p 所指结点之间路径长度的函数。

解:在后序遍历非递归算法中,当访问的结点为p 时,其祖先点正好全部在栈中,此时栈中结点的个数就是根结点到p 所指结点之间路径长度。 #includetypedef struct node /*二叉树结点定义*/ { datatype data;

struct node *lchild,*rchild; }bintnode;

typedef bintnode *bintree;

typedef struct stack {

bintree data[100]; int tag[100]; int top; }seqstack;

void creat(bintree *t) ;

/*函数Depth,功能:求根结点到x 的路径长度*/ int Depth(bintree t,datatype x) {

seqstack s; int i=0,j; s.top=0;

while(t || s。top!=0) {

while(t)

s。data[s.top]=t; s。tag[s.top]=0; s.top++;

t=t—〉lchild; }

while(s。top>0 && s.tag[s.top—1]) {

s。top——;

t=s。data[s.top];

if(t->data==x) return s.top; //此时栈中的结点都是x 的祖先结点

if(s。top〉0) {

t=s。data[s。top—1]; s.tag[s.top—1]=1; t=t->rchild; }

else t=NULL; } }

第6章 树

6。1 树最适合用来表示具有( 有序 )性和( 层次 )性的数据。

6.2 在选择存储结构时,既要考虑数据值本身的存储,还需要考虑( 数据间关系 ) 的存储。

6。3 对于一棵具有n 个结点的树,该树中所有结点的度数之和为( n-1 )。 6.4 已知一棵树如图6.11 所示,试回答以下问题:

(1)树中哪个结点为根结点?哪些结点为叶子结点? 答:A 是根结点;E,G,H,I,C,J,K,L 为叶结点。 (2)结点B 的双亲为哪个结点?其子女为哪些结点? 答:B 的双亲结点是A,其子女结点为E 和F。

(3)哪些结点为结点I 的祖先?哪些结点为结点B 的子孙?

答:F,B,A 是结点I 的祖先结点;E,F,G,H,I 是B 的子孙结点。 (4)哪些结点为结点D 的兄弟?哪些结点为结点K 的兄弟? 答:B,C,L 是结点D 的兄弟结点,J 是结点K 的兄弟结点。 (5)结点J 的层次为多少?树的高度为多少? 答:结点J 的层次为3,树的高度为4。

(6)结点A、C 的度分别为多少?树的度为多少? 答:结点A 的度为4,结点C 的度是0,树的度是4。 (7)以结点B 为根的子树的高度为多少? 答:以结点B 为根的子树的高度是3.

(8)试给出该树的括号表示及层号表示形式。

答:该树的括号表示为:A(B(E,F(G,H,I)),C,D(J,K),L),该树的层号 表示为:10A,20B,30E,30F,40G,40H,40I,20C,20D,25J,25K,20L 6。5 试写出图6.11 所示树的前序遍历、后序遍历和层次遍历的结果。

答: 前序遍历:ABEFGHICDJKL 后序遍历:EGHIFBCJKDLA 层次遍历:ABCDLEFJKGHI

6。9 假设树采用指针方式的孩子表示法表示,试编写一个非递归函数,实现树的后序遍历算法。 答:

#include \"tree.h”

int PostOrderByStack (TreeNode *root) {

TreeNode *temp;

TreeNode *stack[MAXLEN];

// childSeq 表示当前打印到了此树第几个孩子,

int top,childSeq[MAXLEN]; int i;

top = —1; //初始化空栈

temp = root; while (1) {

while (temp != NULL)

{

for (i = 0;i < MAXN;i++)

{ if (temp—〉child[i] != NULL) { childSeq[++top] = i + 1;

stack[top] = temp;

temp = temp—>child[i]; break; }

}

// 如果此节点是叶子节点,则输出该结点 if (i == MAXN)

{ printf (\"%5c”,temp—〉key); temp = NULL; break; } }

while (top != —1 ) {

for (i = childSeq[top];i 〈 MAXN;i++) {

if (stack[top]—〉child[i] != NULL) {

temp = stack[top]—〉child[i]; childSeq[top] = i + 1; break; } }

if (i == MAXN) {

printf (”%5c”,stack[top]-〉key); top—-; }

if (temp != NULL) {

break; } }

if (top == -1) {

return 1;

} } }

int main ()

{ char string[MAXLEN]; TreeNode *root = NULL;

printf (”请用树的括号表示法输入一棵树:\\n”); scanf (”%s”,string);

root = CreateTree (root,string); PostOrderByStack (root); return 0; }

因篇幅问题不能全部显示,请点此查看更多更全内容

Top