第七章图 习题答案_第1页
第七章图 习题答案_第2页
第七章图 习题答案_第3页
第七章图 习题答案_第4页
第七章图 习题答案_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/第七章图习题答案基础知识:7。1在图7.23所示的各无向图中:ﻫ

(1)找出所有的简单环。ﻫ(2)哪些图是连通图?对非连通图给出其连通分量.

(3)哪些图是自由树(或森林)?

答:(1)所有的简单环:(同一个环可以任一顶点作为起点)

(a)1231

(b)无ﻫ(c)1231、2342、12341ﻫ(d)无

(2)连通图:ﻫ(a)、(c)、(d)是连通图,

(b)不是连通图,因为从1到2没有路径.具体连通分量为:ﻫﻫ(3)自由树(森林):自由树是指没有确定根的树,无回路的连通图称为自由树:ﻫ(a)不是自由树,因为有回路.ﻫ(b)是自由森林,其两个连通分量为两棵自由树。ﻫ(c)不是自由树。

(d)是自由树。7。2在图7.24(下图)所示的有向图中:ﻫﻫ(1)该图是强连通的吗?若不是,则给出其强连通分量。

(2)请给出所有的简单路径及有向环。ﻫ(3)请给出每个顶点的度,入度和出度.

(4)请给出其邻接表、邻接矩阵及逆邻接表。ﻫ答:(1)该图是强连通的,所谓强连通是指有向图中任意顶点都存在到其他各顶点的路径.ﻫ(2)简单路径是指在一条路径上只有起点和终点可以相同的路径:ﻫ有v1v2、v2v3、v3v1、v1v4、v4v3、v1v2v3、v2v3v1、v3v1v2、v1v4v3、v4v3v1、v3v1v4、另包括所有有向环,有向环如下:ﻫv1v2v3v1、v1v4v3v1(这两个有向环可以任一顶点作为起点和终点)

(3)每个顶点的度、入度和出度:ﻫD(v1)=3ID(v1)=1OD(v1)=2ﻫD(v2)=2ID(v2)=1OD(v2)=1ﻫD(v3)=3ID(v3)=2OD(v3)=1ﻫD(v4)=2ID(v4)=1OD(v4)=1

(4)邻接表:(注意边表中邻接点域的值是顶点的序号,这里顶点的序号是顶点的下标值-1)ﻫ

vertexfirstedge

next

┌─┬─┐

┌─┬─┐

┌─┬─┐ﻫ0│v1│─→│1│─→│3│∧│

├─┼─┤

├─┼─┤

└─┴─┘

1│v2│─→│2│∧│

├─┼─┤

├─┼─┤

2│v3│─→│0│∧│ﻫ

├─┼─┤

├─┼─┤

3│v4│─→│2│∧│

└─┴─┘

└─┴─┘ﻫ

逆邻接表:ﻫ

┌─┬─┐

┌─┬─┐ﻫ

0│v1│─→│2│∧│

├─┼─┤

├─┼─┤

1│v2│─→│0│∧│

├─┼─┤

├─┼─┤

┌─┬─┐ﻫ

2│v3│─→│1│─→│3│∧│

├─┼─┤

├─┼─┤

└─┴─┘

3│v4│─→│0│∧│ﻫ

└─┴─┘

└─┴─┘ﻫ

邻接矩阵:

0101

0010

1000ﻫ

00107.3假设图的顶点是A,B.。.,请根据下述的邻接矩阵画出相应的无向图或有向图。

┌┓ﻫ

|01100|ﻫ

|0111|

|00010|

|1011|

|00010|

|1101|

|10001|

|1110|

|01010|

┙┕

(a)

(b)

答:ﻫ

7。4假设一棵完全二叉树包括A,B,C。。.等七个结点,写出其邻接表和邻接矩阵。ﻫ解:

邻接表如下:

┌─┬─┐

┌─┬─┐

┌─┬─┐

0│A│─→│1│

─→│2│∧│

├─┼─┤

├─┼─┤

├─┼─┤

┌─┬─┐ﻫ

1│B│─→│0│─→│3│─→│4│∧│ﻫ

├─┼─┤

├─┼─┤

├─┼─┤

├─┼─┤

2│C│─→│0│─→│5│─→│6│∧│

├─┼─┤

├─┼─┤

└─┴─┘

└─┴─┘ﻫ

3│D│─→│1│∧│ﻫ

├─┼─┤

├─┼─┤

4│E│─→│1│∧│ﻫ

├─┼─┤

├─┼─┤ﻫ

5│F│─→│2│∧│ﻫ

├─┼─┤

├─┼─┤

6│G│─→│2│∧│

└─┴─┘

└─┴─┘ﻫ

邻接矩阵如下:

0110000ﻫ

1001100

1000011

0100000ﻫ

0100000

0010000ﻫ

00100007。5对n个顶点的无向图和有向图,采用邻接矩阵和邻接表表示时,如何判别下列有关问题?ﻫ

(1)图中有多少条边?

(2)任意两个顶点i和j是否有边相连?

(3)任意一个顶点的度是多少?

答:

对于n个顶点的无向图和有向图,用邻接矩阵表示时:ﻫ

(1)设m为矩阵中非零元素的个数

无向图的边数=m/2

有向图的边数=m

(2)无论是有向图还是无向图,在矩阵中第i行,第j列的元素若为非零值,则该两顶点有边相连。ﻫ(3)对于无向图,任一顶点i的度为第i行中非零元素的个数。ﻫ对于有向图,任一顶点i的入度为第i列中非零元素的个数,出度为第i行中非零元素的个数,度为入度出度之和。ﻫ当用邻接表表示时:ﻫ(1)对于无向图,图中的边数=边表中结点总数的一半。ﻫ对于有向图,图中的边数=边表中结点总数。

(2)对于无向图,任意两顶点间是否有边相连,可看其中一个顶点的邻接表,若表中的adjvex域有另一顶点位置的结点,则表示有边相连。ﻫ对于有向图,则表示有出边相连。

(3)对于无向图,任意一个顶点的度则由该顶点的边表中结点的个数来决定。ﻫ对于有向图,任意一个顶点的出度由该顶点的边表中结点的个数来决定,入度则需遍历各顶点的边表.(用逆邻接表可容易地得到其入度。)7。6n个顶点的连通图至少有几条边?强连通图呢?

答:n个顶点的连通图至少有n—1条边,强连通图至少有2(n-1)条边.7.7DFS和BFS遍历各采用什么样的数据结构来暂存顶点?当要求连通图的生成树的高度最小,应采用何种遍历?

答:DFS遍历采用栈来暂存顶点。BFS采用队列来暂存顶点。当要求连通图的生成树的高度最小时,应采用BFS遍历。7。8画出以顶点v1为初始源点遍历图7。25(下图)所示的有向图所得到的DFS和BFS生成森林。ﻫ

答:

7.9按顺序输入顶点对:(1,2),(1,6),(2,6),(1,4),(6,4),(1,3),(3,4),(6,5),(4,5),(1,5),(3,5),根据第7.2。2节中算法CreatALGraph画出相应的邻接表。并写出在该邻接表上,从顶点4开始搜索所得的DFS和BFS序列,及DFS和BFS生成树。

ﻫ答:相应的邻接表如下:

┌─┬─┐

┌─┬─┐

┌─┬─┐

┌─┬─┐

┌─┬─┐

┌─┬─┐

1│1│─→│5│─→│3│─→│4│─→│6│─→│2│∧│

├─┼─┤

├─┼─┤

├─┼─┤

└─┴─┘

└─┴─┘

└─┴─┘ﻫ

2│2│─→│6│─→│1│∧│

├─┼─┤

├─┼─┤

├─┼─┤

┌─┬─┐

3│3│─→│5│─→│4│─→│1│∧│ﻫ

├─┼─┤

├─┼─┤

├─┼─┤

├─┼─┤

┌─┬─┐

4│4│─→│5│─→│3│─→│6│─→│1│∧│ﻫ

├─┼─┤

├─┼─┤

├─┼─┤

├─┼─┤

├─┼─┤ﻫ

5│5│─→│3│─→│1│─→│4│─→│6│∧│

├─┼─┤

├─┼─┤

├─┼─┤

├─┼─┤

├─┼─┤

6│6│─→│5│─→│4│─→│2│─→│1│∧│

└─┴─┘

└─┴─┘

└─┴─┘

└─┴─┘

└─┴─┘

根据上面的邻接表画出的图见下图:

ﻫﻫ

从顶点4开始搜索所得的DFS序列是:453162ﻫ

从顶点4开始搜索所得的BFS序列是:453612ﻫ

相应的生成树见上图。7.10什么样的图其最小生成树是唯一的?用PRIM和Kruskal求最小生成树的时间各为多少?它们分别适合于哪类图?

答:当候选轻边集中的轻边数始终等于1条时,其最小生成树是唯一的。用Prim和Kruskal求最小生成树的时间复杂度分别为O(n2)和O(elge),前者适合于稠密图,后者适合于稀疏图.7.11对图7。26(下图)所示的连通图,请分别用Prim和Kruskal算法构造其最小生成树。

ﻫﻫ答:

7。12对图7。27(下图)所示的有向图,试利用Dijkstra算法求出从源点1到其它各顶点的最短路径,并写出执行算法过程中扩充红点集的每次循环状态(见表7.2).

答:循环状态表如下:ﻫ循环

红点集

KD[1]D[2]D[3]D[4]D[5]D[6]P[1]P[2]P[3]P[4]P[5]P[6]

初始化

{1}

-

0

20

15

—1

1

1

-1

-1

—1

1

{1,3}

3

0

19

15

25

-1

1

-1

—1

3

{1,3,2}

2

0

19

15

29

25

-1

3

1

-1

3

3

{1,3,2,6}

6

0

19

15

29

29

25

—1

1

6

3

4

{1,3,2,6,4}

4

0

19

15

29

29

25

-1

1

6

2

3

5{1,3,2,6,4,5}

5

19

15

29

29

25

-1

1

6

2

同上

同上

同上

从源点1到各点的路径如下所示:

1到2:132

1到3:13

1到4:1364

1到5:1325

1到6:136ﻫ整个执行算法过程中的扩充红点集的每次循环状态见上表.7。13试写出图7.28(下图)所示有向图的所有拓扑序列,并指出就用7.6节给出的NonPreFirstTopSort算法求得的是哪个序列,设邻接表的边表结点中的邻接点序号是递增有序的。

ﻫ答:

上图中所有拓扑序列如下:ﻫ

v0v1v5v2v3v6v4*

v0v1v5v2v6v3v4

v0v1v5v6v2v3v4

v1v0v5v6v2v3v4

v1v0v5v2v3v6v4

v1v0v5v2v6v3v4

v1v5v0v2v3v6v4

v1v5v0v2v6v3v4

v1v5v0v6v2v3v4ﻫ

v5v1v0v2v3v6v4

v5v1v0v2v6v3v4

v5v1v0v6v2v3v4

v5v0v1v2v3v6v4

v5v0v1v2v6v3v4

v5v0v1v6v2v3v4

v0v5v6v1v2v3v4

v1v5v6v0v2v3v4

v5v6v1v0v2v3v4ﻫ

v5v6v0v1v2v3v4

v5v0v6v1v2v3v4

v5v1v6v0v2v3v4

用NonPreFirstTopSort算法求得的是v0v1v5v2v3v6v4也就是上面带*号的那个。7.14什么样的DAG的拓扑序列是唯一的?

ﻫ答:

确定了排序的源点,DAG图中无前趋顶点只有一个且从该点到终点只有一条路径时,它的拓扑序列才是唯一的。7.15请以V0为源点,给出用DFS搜索图7.28(下图)得到的逆拓扑序列.

答:

逆拓扑序列是:V4V2V1V0V1V6V5算法设计:7.16试在无向图的邻接矩阵和邻接链表上实现如下算法:

(1)往图中插入一个顶点

(2)往图中插入一条边

(3)删去图中某顶点ﻫ(4)删去图中某条边

解:(一)用邻接矩阵表示ﻫ#defineMaxVertexNuml00//最大顶点数,应由用户定义

typedefcharVertexType;//顶点类型应由用户定义ﻫtypedefintEdgeType;//边上的权值类型应由用户定义ﻫtypedefstruct{ﻫVextexTypevexs[MaxVertexNum]//顶点表

EdeTypeedges[MaxVertexNum][MaxVertexNum];ﻫ//邻接矩阵,可看作边表

intn,e;//图中当前的顶点数和边数ﻫ}MGragh;

(1)往图中插入一个顶点

voidAddVertexMGraph(MGraph*G,VertexTypex)

{//往无向图的邻接矩阵中插入顶点ﻫif(G->n〉=MaxVertexNum)

Error(”顶点数太多");ﻫG-〉vexs[G-〉n]=x;//将新顶点输入顶点表ﻫG—〉n++;//顶点数加1ﻫ}ﻫ(2)往图中插入一条边

voidAddedgeMGraph(MGraph*G,VertexTypex,VertexTypey)

{//往无向图的邻接矩阵中插入边(x,y)ﻫinti,j,k;ﻫi=—1;j=—1;ﻫfor(k=0;k<G-〉n;k++)//查找X,Y的编号

{if(g—〉vexs[k]===x)i=k;

if(g->vexs[k]==y)j=k;ﻫ}ﻫif(i==—1||j==—1)Error("结点不存在");

else{//插入边(x,y)

g—>vex[i][j]=1;ﻫg-〉vex[j][i]=1;ﻫG—>e++;//边数加1ﻫ}

(3)删去图中某顶点ﻫvoidDeleteVertexMGraph(MGraph*G,VertexTypex)

{//无向图的邻接矩阵中删除顶点xﻫinti,k,j;ﻫi=—1;ﻫfor(k=0;k<G->n;k++)//查找X的编号ﻫif(g—〉vexs[k]=x)i=k;ﻫif(i==-1)Error(”结点不存在”);ﻫelse{//删除顶点以及边

k=0;//求出与x结点相关联的边数kﻫfor(j=0;j〈G—>n;j++)ﻫif(g-〉vexs[i][j]==0)k++;

G->e=G->e-k;//设置新的边数ﻫfor(k=i+1;k<G—〉n;k++)//在邻接矩阵中删除第i行ﻫfor(j=0;j〈G—>n;j++)ﻫg->vexs[k-1][j]=g—>vexs[k][j];

for(k=i+1;k<G->n;k++)//在邻接矩阵中删除第i列ﻫfor(j=0;j<G—〉n;j++)

g—〉vexs[j][k-1]=g->vexs[j][k];

G->n-—;//总结点数-1

ﻫ(4)删去图中某条边

voidDeleteedgeMGraph(MGraph*G,VertexTypex,VertexTypey)

{//无向图的邻接矩阵中删除边(x,y)

inti,j,k;

i=-1;j=—1;ﻫfor(k=0;k〈G->n;k++)//查找X,Y的编号

{if(g—〉vexs[k]=x)i=k;ﻫif(g->vexs[k]=y)j=k;ﻫ}ﻫif(i==—1||j==-1)Error("结点不存在”);ﻫelseif(g->vexs[i][j]!=1)

{//删除边(x,y)ﻫg—〉vex[i][j]=0;

g->vex[j][i]=0;ﻫG->e—-;//边数加1

}ﻫ}ﻫ(二)用邻接表表示

ﻫtypedefstructnode{//边表结点ﻫintadjvex;//邻接点域

structnode*next;//链域ﻫ//若要表示边上的权,则应增加一个数据域ﻫ}EdgeNode;

typedefstructvnode{//顶点表结点

VertexTypevertex;//顶点域ﻫEdgeNode*firstedge;//边表头指针ﻫ}VertexNode;ﻫtypedefVertexNodeAdjList[MaxVertexNum];//AdjList是邻接表类型ﻫtypedefstruct{ﻫAdjListadjlist;//邻接表ﻫintn,e;图中当前顶点数和边数

ﻫ}ALGraph;//对于简单的应用,无须定义此类型,可直接使用AdjList类型。

(1)往图中插入一个顶点ﻫvoidAddVertexALGraPh(ALGrahp*G,VertexTypex)

{//往无向图的邻接表表示中插入一个顶点ﻫif(G—>n>=MaxVertexNum)

Error("顶点数太多”);

G->adjlist[G->n].vertex=x;//将新顶点输入顶点表ﻫG-〉adjlist[G—>n].firstedge=NULL;//边表置为空表ﻫG->n++;//顶点数加1

}ﻫ(2)往图中插入一条边

voidAddedgeALGraPh(ALGrahp*G,VertexTypex,VertexTypey)

{//往无向图的邻接表中插入边(x,y)ﻫinti,j,k;ﻫEdgeNode*s;ﻫi=—1;j=-1;

for(k=0;k<G—>n;k++)//查找X,Y的编号

{if(G-〉adjlist[k].vertex==x)i=k;ﻫif(G—>adjlist[k].vertex==y)j=k;ﻫ}

if(i==-1||j==—1)Error("结点不存在");

else{

s=G-〉adjlist[i]。firstedge;

while((s)&&(s—>adjvex!=j)//查看邻接表中有无(x,y)ﻫs=s->next;

if(!s)//当邻接表中无边(x,y),插入边(x,y)

{

s=(EdgeNode*)malloc(sizeof(EdgeNode));//生成边表结点ﻫs-〉adjvex=j;//邻接点序号为jﻫs->next=G->adjlist[i]。firstedge;ﻫG->adjlist[i].firstedge=s;//将新结点*s插入顶点x的边表头部

s=(EdgeNode*)malloc(sizeof(EdgeNode));ﻫs->adjvex=i;//邻接点序号为i

s->next=G-〉adjlist[j].firstedge;ﻫG—〉adjlist[j]。firstedge=s;//将新结点*s插入顶点x的边表头部

G->e++;//边数加1ﻫ}

}ﻫ}

ﻫ(3)删去图中某顶点

voidDeleteVertexALGraPh(ALGrahp*G,VertexTypex)

{//无向图的邻接表中删除顶点x

inti,k,j;ﻫEdgeNode*s,*p,*q;

i=—1;ﻫfor(k=0;k<G-〉n;k++)//查找X的编号ﻫif(G->adjlist[k].vertex==x)i=k;ﻫif(i==-1)Error(”结点不存在");ﻫelse{//删除与x相关联的边ﻫs=G-〉adjlist[i].firstedge;ﻫwhile(s)ﻫ{p=G-〉adjlist[s-〉adjvex].firstedge;//删除与i相关联的其他结点边表中表结点

if(p)&&(p-〉adjvex==i)//是第一个边表结点,修改头指针ﻫ{G—>adjlist[s->adjvex]。firstedge=p-〉next;

free(p);

}ﻫelse//不是第一个边表结点,查找并删除

{while(p)&&(p—>next)&&(p—〉next—>adjvex==i)ﻫp=p->next;ﻫq=p-〉next;ﻫp->next=q->next;free(q);ﻫ}

q=s;s=s—>next;free(q);//在i结点的边表中删除表结点

G—>e-—;

//调整顶点表

for(j=i;j<G->n—1;j++)

{G—>adjlist[j].firstedge=G—>adjlist[j+1].firstedge;ﻫG->adjlist[j].vertex=G-〉adjlist[j+1]。vertex;

}ﻫG—>n—-;

}

}

(4)删去图中某条边ﻫvoidDeleteedgeALGraPh(ALGraph*G,VertexTypex,VertexTypey)

{//往无向图的邻接表中删除边(x,y)ﻫinti,j,k;

EdgeNode*s,*p;

i=-1;j=-1;ﻫfor(k=0;k<G-〉n;k++)//查找X,Y的编号

{if(G-〉adjlist[k].vertex==x)i=k;

if(G—>adjlist[k]。vertex==y)j=k;

}

if(i==-1||j==-1)Error("结点不存在");

else{ﻫs=G->adjlist[i].firstedge;//在i的边表中删除值为j的边表结点

if(s)&&(s—〉adjvex==j)

{G-〉adjlist[i]。firstedge=s—>next;ﻫfree(s);ﻫ}

else{

while(s)&&(s—〉next)&&(s->next—〉adjvex!=j)

s=s-〉next;

if(!s-〉next)Error("无此边");ﻫelse

ﻫ{p=s->next;s=p->next;free(p);ﻫ}

}ﻫs=G->adjlist[j].firstedge;//在j的边表中删除值为i的边表结点

if(s)&&(s-〉adjvex==i)

ﻫ{G—〉adjlist[j].firstedge=s—〉next;

free(s);

}

ﻫelse{

while(s)&&(s->next)&&(s-〉next—〉adjvex!=j)

s=s—>next;ﻫp=s->next;s=p->next;free(p);ﻫ}ﻫG—>e——;

}ﻫ}

7。17下面的伪代码是一个广度优先搜索算法,试以图7。29(下图)中的v0为源点执行该算法,请回答下述问题:ﻫﻫ(1)对图中顶点vn+1,它需入队多少次?它被重复访问多少次?ﻫ(2)若要避免重复访问同一个顶点的错误,应如何修改此算法?

voidBFS(ALGraph*G,intk)

{//以下省略局部变量的说明,visited各分量初值为假

InitQueue(&Q);//置空队列

EnQueue(&Q,k);//k入队ﻫwhile(!QueueEmpty(&Q)){ﻫi=DeQueue(&Q);//vi出队ﻫvisited[i]=TRUE;//置访问标记

printf("%c",G—>adjlist[i].vertex;//访问vi

for(p=G—>adjlist[i]。firstedge;p;p=p—>next)ﻫ//依次搜索vi的邻接点vj(不妨设p—〉adjvex=j)

if(!visited[p->adjvex])//若vj没有访问过

EnQueue(&Q,p-〉adjvex);//vj入队ﻫ}//endofwhileﻫ}//BFSﻫ答:(1)对图中顶点vn+1,它需入队n次,它被重复访问n次.ﻫ(2)若要避免重复访问同一个顶点的错误,应作如下修改:ﻫvoidBFS(ALGraph*G,intk)ﻫ{//以下省略局部变量的说明,visited各分量初值为假

InitQueue(&Q);//置空队列

EnQueue(&Q,k);//k入队

visited[i]=TRUE;//置访问标记ﻫprintf(”%c",G—>adjlist[i]。vertex;//访问viﻫwhile(!QueueEmpty(&Q)){

i=DeQueue(&Q);//vi出队

for(p=G-〉adjlist[i].firstedge;p;p=p—>next)ﻫ//依次搜索并访问vi的未访问邻接点vj(不妨设p—>adjvex=j)

if(!visited[p->adjvex])//若vj没有访问过ﻫ{printf(”%c",G—〉adjlist[i]。vertex;//访问vjﻫEnQueue(&Q,p->adjvex);//vj入队

}//endofwhile

)//BFS7.18试以邻接表和邻接矩阵为存储结构,分别写出基于DFS和BFS遍历的算法来判别顶点vi和vj(i<>j)之间是否有路径。

答:(1)基于采用邻接矩阵的DFS

intpathDFSM(MGraph*G,inti,intj)

{//以邻接矩阵为存储结构,判断vi和vj之间是否有路径,若有返回1,否则返回0ﻫintk;

visited[i]=TRUE;

for(k=0;k<G-〉n;k++)//依次搜索vi的邻接点ﻫif(G-〉edges[i][k]==1&&!visited[k])ﻫif(k==j)return1;//有路径相通

elsereturn(pathDFSM(G,k,j);ﻫreturn0;//无路径相通ﻫ}//DFSMﻫ(2)基于采用邻接表的DFS

ﻫintPATHDFS(ALGraph*G,inti,intj){

//以邻接表为存储结构,判断vi和vj之间是否有路径,若有返回1,否则返回0

EdgeNode*p;

visited[i]=TRUE;//标记vi已访问ﻫp=G->adjlist[i].firstedge;//取vi边表的头指针ﻫwhile(p){//依次搜索vi的邻接点vk,这里k=p—〉adjvexﻫif(!visited[p->adjvex])//若vk尚未被访问

if(p—〉adjvex==j)ﻫreturn1;

elseruturnPATHDFS(g,p—〉adjvex,j);//则以Vk为出发点向纵深搜索ﻫp=p—〉next;//找vi的下一邻接点ﻫ}ﻫreturn0;

}//PATHDFS

(3)基于邻接矩阵的BFS算法ﻫintpathBFSM(MGraph*G,inti,intj)ﻫ{//以邻接矩阵为存储结构,判断vi和vj之间是否有路径,若有返回1,否则返回0ﻫintk;ﻫCirQueueQ;

initQueue(&Q);ﻫvisited[i]=TRUE;

EnQueue(&Q,i);ﻫwhile(!QueueEmpty(&Q)){ﻫi=DeQueue(&Q);//vi出队

for(k=0;k<G-〉n;k++)//依次搜索vi的邻接点vkﻫif(G—〉edges[i][k]==1&&!visited[k]){//vk未访问ﻫif(k==j)return1;ﻫvisited[k]=TRUE;

EnQueue(&Q,k);//访问过的vk人队

}//endwhileﻫreturn0;ﻫ}//pathBFSMﻫ(4)基于邻接表为存储结构的BFS算法ﻫintBFS(ALGraph*G,inti,intj)

{//以邻接表为存储结构,判断vi和vj之间是否有路径,若有返回1,否则返回0

inti;

CirQueueQ;//须将队列定义中DataType改为int

EdgeNode*p;

InitQueue(&Q);//队列初始化ﻫvisited[i]=TRUE;

ﻫEnQueue(&Q,i);//vi已访问,将其人队.(实际上是将其序号人队)ﻫwhile(!QueueEmpty(&Q)){//队非空则执行ﻫi=DeQueue(&Q);//相当于vi出队

p=G->adjlist[i].firstedge;//取vi的边表头指针

while(p){//依次搜索vi的邻接点vk(令p—〉adjvex=k)

if(!visited[p->adjvex])//若vk未访问过ﻫif(p-〉adjvex==j)

return1;ﻫelse{

visited[P-〉adjvex]=TRUE;

ﻫEnQueue(&Q,p->adjvex);

}//访问过的vk人队ﻫ

p=p—>next;//找vi的下一邻接点

}//endwhile

}//endwhileﻫ

return0;

}//endofpathBFS7.19试分别写出求DFS和BFS生成树(或生成森林)的算法,要求打印出所有的树边。

答:(1)求DFS生成树

typedefenum{FALSE,TRUE}Boolean;//FALSE为0,TRUE为1

Booleanvisited[MaxVertexNum];//访问标志向量是全局量

voidDFSTraverseTREE(ALGraph*G)ﻫ{//求深度优先生成树(以邻接表表示的图G),而以邻接矩阵表示G时,

//算法完全与此相同,只要将DFSTree(G,i)改为DFSMTree(G,i)即可

inti;

for(i=0;i<G->n;i++)ﻫvisited[i]=FALSE;//标志向量初始化ﻫfor(i=0;i<G->n;i++)ﻫif(!visited[i])//vi未访问过ﻫDFSTree(G,i);//以vi为源点开始DFS搜索,求DFS生成树的边ﻫ}//DFSTraverse

voidDFSTree(ALGraph*G,inti){

//以vi为出发点对邻接表表示的图G进行深度优先搜索,打印生成树(生成森林)的边ﻫEdgeNode*p;

visited[i]=TRUE;//标记vi已访问

p=G-〉adjlist[i].firstedge;//取vi边表的头指针

while(p){//依次搜索vi的邻接点vj,这里j=p-〉adjvex

if(!visited[p->adjvex])//若vj尚未被访问ﻫ{printf("(%c,%c)\n”,G—>adjlist[i].vertex,G-〉adjlist[p—>adjvex].vertex)

//打印边

DFSTree(g,p-〉adjvex);//则以Vj为出发点向纵深搜索ﻫ}

p=p->next;//找vi的下一邻接点

}

}//DFS

voidDFSMTree(MGraph*G,inti)ﻫ{//以vi为出发点对邻接矩阵表示的图G进行深度优先搜索,打印生成树(生成森林)的边

intj;ﻫvisited[i]=TRUE;

for(j=0;j<G->n;j++)//依次搜索vi的邻接点

if(G—〉edges[i][j]==1&&!visited[j])ﻫ{

printf(”(%c,%c)\n”,G—〉vexs[i],G->vexs[j]);//打印边

DFSMTree(G,j);//(vi,vj)∈E,且vj未访问过,故vj为新出发点

}

}//DFSMTreeﻫ(2)求BFS生成树ﻫtypedefenum{FALSE,TRUE}Boolean;//FALSE为0,TRUE为1

Booleanvisited[MaxVertexNum];//访问标志向量是全局量ﻫvoidBFSTraverseTREE(ALGraph*G)

{//求广度优先生成树(以邻接表表示的图G),而以邻接矩阵表示G时,

//算法完全与此相同,只要将BFSTree(G,i)改为BFSMTree(G,i)即可ﻫ

inti;ﻫ

for(i=0;i<G—>n;i++)ﻫ

visited[i]=FALSE;//标志向量初始化

for(i=0;i<G-〉n;i++)ﻫif(!visited[i])//vi未访问过ﻫBFSTree(G,i);//以vi为源点开始BFS搜索,求BFS生成树的边ﻫ}//BFSTraverseﻫvoidBFSTree(ALGraph*G,intk)

{//以vk为源点对用邻接表表示的图G进行广度优先搜索,并求出BFS生成树边ﻫinti;ﻫCirQueueQ;//须将队列定义中DataType改为intﻫEdgeNode*p;

InitQueue(&Q);//队列初始化

visited[k]=TRUE;

EnQueue(&Q,k);//vk已访问,将其人队。(实际上是将其序号人队)ﻫwhile(!QueueEmpty(&Q)){//队非空则执行

i=DeQueue(&Q);//相当于vi出队

p=G-〉adjlist[i].firstedge;//取vi的边表头指针

while(p){//依次搜索vi的邻接点vj(令p—>adjvex=j)

if(!visited[p->adivex]){//若vj未访问过

printf("(%c,%c)\n",G-〉adjlist[i].vertex,G-〉adjlist[p—>adjvex].vertex);

//打印边ﻫvisited[P—>adjvex]=TRUE;

ﻫEnQueue(&Q,p—〉adjvex);//访问过的vj人队

}//endifﻫp=p->next;//找vi的下一邻接点ﻫ}//endwhileﻫ}//endwhileﻫ}//endofBFSTree

ﻫvoidBFSMTree(MGraph*G,intk)

{//以vk为源点对用邻接矩阵表示的图G进行广度优先搜索,并求出BFS生成树边ﻫinti,j;ﻫCirQueueQ;

InitQueue(&Q);

visited[k]=TRUE;

EnQueue(&Q,k);

while(!QueueEmpty(&Q)){

i=DeQueue(&Q);//vi出队ﻫfor(j=0;j〈G-〉n;j++)//依次搜索vi的邻接点vj

if(G->edges[i][j]==1&&!visited[j]){//vi未访问ﻫprintf(”(%c,%c)\n",G->vexs[i],G->vexs[j]);//打印边ﻫvisited[j]=TRUE;

EnQueue(&Q,j);//访问过的vj人队ﻫ}ﻫ}//endwhileﻫ}//BFSMTree7.20写一算法求连通分量的个数并输出各连通分量的顶点集。

答:typedefenum{FALSE,TRUE}Boolean;//FALSE为0,TRUE为1ﻫBooleanvisited[MaxVertexNum];//访问标志向量是全局量ﻫvoidDFSTraverse(ALGraph*G)ﻫ{//深度优先遍历以邻接表表示的图G,求连通分量的个数和各连通分量的顶点集ﻫinti;

for(i=0;i〈G-〉n;i++)

visited[i]=FALSE;//标志向量初始化ﻫj=0;//连通分量个数计数器ﻫfor(i=0;i<G—>n;i++)

if(!visited[i])//vi未访问过

{j++;ﻫprintf("connectedcomponent%d:{”,j);

DFS(G,i);//以vi为源点开始DFS搜索ﻫprintf(”}\n");

}

}//DFSTraverseﻫvoidDFS(ALGraph*G,inti){

ﻫ//以vi为出发点对邻接表表示的图G进行深度优先搜索ﻫEdgeNode*p;

printf("%c,”,G—>adjlist[i]。vertex);//访问顶点viﻫvisited[i]=TRUE;//标记vi已访问

p=G->adjlist[i].firstedge;//取vi边表的头指针ﻫwhile(p){//依次搜索vi的邻接点vj,这里j=p-〉adjvexﻫif(!visited[p—〉adjvex])//若vi尚未被访问

DFS(g,p->adjvex);//则以Vj为出发点向纵深搜索

p=p—〉next;//找vi的下一邻接点

)//DFS7。21设图中各边的权值都相等,试以邻接矩阵和邻接表为存储结构,分别写出算法:

(1)求顶点vi到顶点vj(i<〉j)的最短路径

(2)求源点vi到其余各顶点的最短路径

要求输出路径上的所有顶点(提示:利用BFS遍历的思想)ﻫ答:(1)求顶点vi到顶点vj(i〈〉j)的最短路径

intshortestpath(ALGraph*G,inti,intj)ﻫ{//对邻接表表示的图G,求顶点vi到顶点vj(i<>j)的最短路径

intdist[MaxVertexNum];ﻫCirQueueQ;//须将队列定义中DataType改为intﻫEdgeNode*p;ﻫintk;

for(k=0;k〈G-〉n;k++)ﻫdist[k]=0;//距离向量初始化ﻫInitQueue(&Q);//队列初始化

visited[i]=TRUE;

ﻫEnQueue(&Q,i);

while(!QueueEmpty(&Q)){//队非空则执行

i=DeQueue(&Q);//相当于vi出队ﻫp=G->adjlist[i].firstedge;//取vi的边表头指针ﻫwhile(p){//依次搜索vi的邻接点vk(令p-〉adjvex=k)ﻫif(!visited[p-〉adjvex]){//若vj未访问过

dist[p->adjvex]++;ﻫif(p->adjvex==j)returndist[p-〉adjvex];ﻫvisited[P->adjvex]=TRUE;

EnQueue(&Q,p—>adjvex);//访问过的vk人队

}//endif

p=p->next;//找vi的下一邻接点

}//endwhileﻫ}//endwhileﻫ}//endofshortestpathﻫﻫintBFSM(MGraph*G,inti,intj)ﻫ{//对邻接链表表示的图G,求顶点vi到顶点vj(i<>j)的最短路径ﻫintdist[MaxVertexNum],k;ﻫCirQueueQ;

initQueue(&Q);

for(k=0;k<G-〉n;k++)

dist[i]=0;//距离向量初始化ﻫvisited[k]=TRUE;ﻫEnQueue(&Q,i);

while(!QueueEmpty(&Q)){ﻫi=DeQueue(&Q);//vi出队

for(k=0;k〈G-〉n;k++)//依次搜索vi的邻接点vk

if(G->edges[i][k]==1&&!visited[k]){//vk未访问ﻫdist[k]++;ﻫif(k==j)returndist[j];ﻫvisited[k]=TRUE;

EnQueue(&Q,k);//访问过的vk人队

}

}//endwhileﻫ}//BFSMﻫ

(2)求源点vi到其余各顶点的最短路径

ﻫvoidshortestpath(ALGraph*G,inti)

{//对邻接表表示的图G,求顶点vi到顶点vj(i<〉j)的最短路径

intdist[MaxVertexNum];ﻫintpre[MaxVertexNum];//pre[k]中存放vi到vk路径中,vk的前趋的序号

CirQueueQ;//须将队列定义中DataType改为intﻫEdgeNode*p;

intk,j;

for(k=0;k<G—>n;k++)

{dist[k]=0;//距离向量初始化ﻫpre[k]=k;ﻫ}

InitQueue(&Q);//队列初始化

visited[i]=TRUE;

ﻫEnQueue(&Q,i);

while(!QueueEmpty(&Q)){//队非空则执行ﻫi=DeQueue(&Q);//相当于vi出队ﻫp=G—>adjlist[i].firstedge;//取vi的边表头指针

while(p){//依次搜索vi的邻接点vk(令p-〉adjvex=k)

if(!visited[p—〉adjvex]){//若vj未访问过ﻫdist[p->adjvex]++;ﻫpre[p-〉adjvex]=i;

visited[P—>adjvex]=TRUE;

ﻫEnQueue(&Q,p—>adjvex);//访问过的vk人队ﻫ}//endif

p=p—〉next;//找vi的下一邻接点

}//endwhileﻫ}//endwhile

for(k=0;k<G—〉n;k++)//打印各顶点的最短路径和长度ﻫ{printf("pathof%cis%d:",G->adjlist[k]。vertex,dist[k]);ﻫ

j=k;ﻫ

printf("%c",G-〉adjlist[k].vertex);ﻫ

doﻫ{ﻫj=pre[j];

print(”〈-%c”,G—>adjlist[j].vertex);ﻫ}ﻫwhile(j!=i);

printf(”\n");

}

}//endofshortestpathﻫﻫvoidshortestpathBFSM(MGraph*G,inti)

{//对邻接矩阵表示的图G,求顶点vi到其他顶点的最短路径

intdist[MaxVertexNum],k,j;

intpre[MaxVertexNum];//pre[k]中存放vi到vk路径中,vk的前趋的序号

CirQueueQ;ﻫinitQueue(&Q);

for(k=0;k<G—〉n;k++)

{dist[k]=0;//距离向量初始化

pre[k]=k;ﻫ}

visited[k]=TRUE;

EnQueue(&Q,i);

while(!QueueEmpty(&Q)){ﻫi=DeQueue(&Q);//vi出队

for(k=0;k〈G—>n;k++)//依次搜索vi的邻接点vk

if(G—>edges[i][k]==1&&!visited[k]){//vk未访问

dist[k]++;

pre[k]=i;ﻫvisited[k]=TRUE;

EnQueue(&Q,k);//访问过的vk人队ﻫ}

}//endwhile

for(k=0;k<G—〉n;k++)//打印各顶点的最短路径和长度ﻫ{printf(”pathof%cis%d:",G->vertex[k],dist[k]);

j=k;ﻫprintf("%c”,G->vertex[k]);ﻫdoﻫ{ﻫj=pre[j];

printf("<-%c”,G->vertex[j]);

}ﻫwhile(j!=i);

printf(”\n”);

}

}//shortestpathBFSM7.22以邻接表为存储结构,写一个基于DFS遍历策略的算法,求图中通过某顶点vk的简单回路(若存在).

答:ﻫintcircleDFS(ALGraph*G,intk){

ﻫ//以vk为出发点对邻接表表示的图G,求简单回路,若存在返回1,否则返回0

EdgeNode*p;

printf("%c”,G—〉adjlist[k].vertex);//访问顶点vk

visited[k]=TRUE;//标记vk已访问ﻫp=G->adjlist[k]。firstedge;//取vk边表的头指针ﻫwhile(p){//依次搜索vk的邻接点vj,这里j=p-〉adjvexﻫif(!visited[p—>adjvex])//若vj尚未被访问ﻫDFS(G,p-〉adjvex);//则以Vj为出发点向纵深搜索ﻫelseif(p-〉adjvex==k)

ﻫ{printf(”%c",G—>adjlist[k]。vertex);return1;}ﻫp=p->next;//找vk的下一邻接点

}

return0;ﻫ}//DFS7.23写一算法求有向图的所有根(若存在),分析算法的时间复杂度。ﻫ

答:

typedefenum{FALSE,TRUE}Boolean;//FALSE为0,TRUE为1ﻫBooleanvisited[MaxVertexNum];//访问标志向量是全局量

voidDFSTraverse(ALGraph*G)

{//对以邻接表表示的有向图G,求所有根(以邻接矩阵表示G时,算法完全与此相同)ﻫinti,j;

for(j=0;j〈G—〉n;j++)

{ﻫfor(i=0;i<G->n;i++)ﻫvisited[i]=FALSE;//标志向量初始化ﻫDFS(G,j);//以vj为源点开始DFS搜索,也可用BFS(G,j)ﻫi=0;ﻫwhile(i<G-〉n)&&(visited[i]==TRUE)ﻫi++;ﻫif(i==G—>n)printf(”root:%c",G-〉adjlist[j].vertex);ﻫ}ﻫ}//DFSTraverse

该算法的为二重循环,若调用的DFS算法的复杂度为O(n+e),所以该算法的时间复杂度为O(n(n+e))

若调用的DFSM算法的复杂度为O(n*n),所以该算法的时间复杂度为O(n^3)7。24改写7。5节的算法Print,使输出的从源点到各终点的最短路径是正向的。(提示:使用栈暂存路径)ﻫﻫ答:ﻫvoidprint(pathp,distanced)ﻫ{//输出最短路径及其长度,从源点到各终点的最短路径是正向的ﻫinti,pre;ﻫSeqStackS;//定义一个栈ﻫInitStack(&s);ﻫfor(i=0;i<n;i++){//依次打印各顶点i的最短路径及其长度ﻫprintf("\ndistance:%d,path:”,d[i]);//输出终点i的最短距离

Push(&S,i);//终点i入栈

pre=p[i];//找终点i的前趋

while(pre!=—1)

{push(&s,pre);ﻫpre=p[pre];//继续找前趋ﻫ}//endwhileﻫprintf("%d”,pop(&s));

while(!StackEmpty(S))

printf(”,%d”,pop(&s));ﻫ}//endfor

ﻫ}//endprint7.25对7.6节的NonSuccFirstTopSort算法求精,分别以邻接矩阵和邻接表作为存储结构,写出其具体算法,并分析算法的时间。ﻫﻫ答:ﻫﻫ(1)以邻接矩阵作为存储结构

voidNonSuccFirstTopSort(MGraphG){//优先输出无后继的顶点

intoutdegree[MaxVertexNum];//出度向量,此处MaxVertexNum〉=G.nﻫSeqStackS,T;//将栈中data向量的基类型改为intﻫinti,j,count=0;//count对输出的顶点数目计数,初值为0ﻫfor(i=0;i<G.n;i++)

outdegree[i]=0;ﻫfor(i=0;i〈G.n;i++)

for(j=0;j<G。n;j++)ﻫoutdegree[i]=outdegree[i]+g.edge[i][j];

InitStack(&s);

for(i=0;i<G。n;i++)ﻫif(outdegree[i]==0)

ﻫPush(&S,i);//出度为0的顶点i入栈

InitStack(&T);ﻫwhile(!StackEmpty(S))//栈非空,有出度为0的顶点

{i=pop(&s);ﻫPush(&T,i);

count++;//顶点计数加1

for(j=0;j〈G。n;j++)//修改以i为弧头的弧的弧尾顶点的出度ﻫif(G.edge[j][i]==1)

{G.edge[j][i]=0;

outdegree[j]——;ﻫif(outdegree[j]==0)//将新生成的出度为0的顶点入栈

ﻫPush(&S,j);//出度为0的顶点j入栈ﻫ}//endofifﻫ}//endofwhile

if(count〈G。n)

printf("G中存在有向环,排序失败!”);ﻫelse{//输出拓扑序列

while(!StackEmpty(T))

printf(”%c”,G.vertex[pop(&T)]);

}ﻫ

(2)以邻接表作为存储结构ﻫvoidNonSuccFirstTopSort(ALGraphG){

//优先输出无后继的顶点,此处用逆邻接表存储ﻫintoutdegree[MaxVertexNum];//出度向量,此处MaxVertexNum>=G.nﻫSeqStackS,T;//将栈中data向量的基类型改为intﻫinti,j,count=0;//count对输出的顶点数目

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论