《数据结构》习题汇编07 第七章 图 试题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第七章图试题
一、单项选择题
1.在无向图中定义顶点的度为与它相关联的()的数目。
A. 顶点
B. 边
C. 权
D. 权值
2.在无向图中定义顶点 v i与v j之间的路径为从v i到达v j的一个()。
A. 顶点序列
B. 边序列
C. 权值总和
D. 边的条数
3.图的简单路径是指()不重复的路径。
A. 权值
B. 顶点
C. 边
D. 边与顶点均
4.设无向图的顶点个数为n,则该图最多有()条边。
A. n-1
B. n(n-1)/2
C. n(n+1)/2
D. n(n-1)
5.n个顶点的连通图至少有()条边。
A. n-1
B. n
C. n+1
D. 0
6.在一个无向图中,所有顶点的度数之和等于所有边数的 ( ) 倍。
A. 3
B. 2
C. 1
D. 1/2
7.若采用邻接矩阵法存储一个n个顶点的无向图,则该邻接矩阵是一个 ( )。
A. 上三角矩阵
B. 稀疏矩阵
C. 对角矩阵
D. 对称矩阵
8.图的深度优先搜索类似于树的()次序遍历。
A. 先根
B. 中根
C. 后根
D. 层次
9.图的广度优先搜索类似于树的()次序遍历。
A. 先根
B. 中根
C. 后根
D. 层次
10.在用Kruskal算法求解带权连通图的最小(代价)生成树时,通常采用一个()辅助结构,
判断一条边的两个端点是否在同一个连通分量上。
A. 位向量
B. 堆
C. 并查集
D. 生成树顶点集合
11.在用Kruskal算法求解带权连通图的最小(代价)生成树时,选择权值最小的边的原则是该边不能
在图中构成()。
A. 重边
B. 有向环
C. 回路
D. 权值重复的边
12.在用Dijkstra算法求解带权有向图的最短路径问题时,要求图中每条边所带的权值必须是
()。
A. 非零
B. 非整
C. 非负
D. 非正
13.在一个连通图中进行深度优先搜索得到一棵深度优先生成树,树根结点是关节点的充要条件是它至少
有()子女。
A. 1
B. 2
C. 3
D. 0
14.设有向图有n个顶点和e条边,采用邻接表作为其存储表示,在进行拓扑排序时,总的计算时间为
()。
A. O(nlog2e)
B. O(n+e)
C. O(ne)
D. O(n2)
15.设有向图有n个顶点和e条边,采用邻接矩阵作为其存储表示,在进行拓扑排序时,总的计算时间为
()。
A. O(nlog2e)
B. O(n+e)
C. O(ne)
D. O(n2)
16.设G1 = (V1, E1) 和G2 = (V2, E2) 为两个图,如果V1 ⊆ V2,E1 ⊆ E2,则称()。
A. G1是G2的子图
B. G2是G1的子图
C. G1是G2的连通分量
D. G2是G1的连通分量
17.有向图的一个顶点的度为该顶点的()。
A. 入度
B. 出度
C. 入度与出度之和
D. (入度﹢出度))/2
18.一个连通图的生成树是包含图中所有顶点的一个()子图。
A. 极小
B. 连通
C. 极小连通
D. 无环
19.n (n>1) 个顶点的强连通图中至少含有()条有向边。
A. n-1
B. n n(n-1)/2 D. n(n-1)
20.在一个带权连通图G中,权值最小的边一定包含在G的()生成树中。
A. 某个最小
B. 任何最小
C. 广度优先
D.深度优先
21.对于具有e条边的无向图,它的邻接表中有()个边结点。
A. e-1
B. e
C. 2(e-1)
D. 2e
22.对于如图所示的带权有向图,从顶点1到顶点5的最短路径为()。
A.1, 4, 5
B. 1, 2, 3, 5
C. 1, 4, 3, 5
D. 1, 2, 4, 3, 5
23.具有n个顶点的有向无环图最多可包含()条有向边。
A. n-1
B. n
C. n(n-1)/2
D.n(n-1)
24.一个有n个顶点和n条边的无向图一定是()。
A. 连通的
B. 不连通的
C. 无环的
D. 有环的
25.在n个顶点的有向无环图的邻接矩阵中至少有()个零元素。
A. n
B. n(n-1)/2
C. n(n+1)/2
D. n(n-1)
26.对于有向图,其邻接矩阵表示比邻接表表示更易于()。
A. 求一个顶点的度
B. 求一个顶点的邻接点
C. 进行图的深度优先遍历
D. 进行图的广度优先遍历
27.在一个有向图的邻接矩阵表示中,删除一条边<vi, vj>需要耗费的时间是()。
A. O(1)
B. O(i)
C. O(j)
D. O(i+j)
28.与邻接矩阵相比,邻接表更适合于存储()图。
A. 无向
B.连通
C.稀疏
D. 稠密图
29.设一个有n个顶点和e条边的有向图采用邻接矩阵表示,要计算某个顶点的出度所耗费的时间是
()。
A. O(n)
B. O(e)
C. O(n+e)
D. O(n2)
30.为了实现图的广度优先遍历,BFS算法使用的一个辅助数据结构是()。
A. 栈
B. 队列
C. 二叉树
D. 树
参考答案: 1. B 2. A 3. B 4. B 5. A
6. B
7. D
8. A
9. D 10. C
11.C 12. C 13. B 14. B 15. D
16. A 17. C 18. C 19. B 20. A
21. D 22. D 23. C 24. D 25. C
26. A 27. A 28. C 29. A 30. B
二、填空题
1.图的定义包含一个顶点集合和一个边集合。
其中,顶点集合是一个有穷________集合。
2.用邻接矩阵存储图,占用存储空间数与图中顶点个数________关,与边数________关。
3.n (n﹥0) 个顶点的无向图最多有________条边,最少有________条边。
4.n (n﹥0) 个顶点的连通无向图最少有________条边。
5.若3个顶点的图G的邻接矩阵为
⎥
⎥
⎥
⎦
⎤
⎢
⎢
⎢
⎣
⎡
1
1
1
,则图G一定是________向图。
6.n (n﹥0) 个顶点的连通无向图各顶点的度之和最少为________。
7.设图G = (V, E),V = {V0, V1, V2, V3}, E = {(V0, V1), (V0, V2), (V0, V3), (V1,
V3)},则从顶点V0开始的图G的不同深度优先序列有________种,例如______________。
8.设图G = (V, E),V = {P, Q, R, S, T}, E = {<P, Q>, <P, R>, <Q, S>, <R, T>},
从顶点P出发,对图G进行广度优先搜索所得的所有序列为__________和___________。
9.n (n﹥0) 个顶点的无向图中顶点的度的最大值为________。
10.在重连通图中每个顶点的度至少为________。
11.在非重连通图中进行深度优先搜索,则深度优先生成树的根为关节点的充要条件是它至少有
________个子女。
12.(n﹥0) 个顶点的连通无向图的生成树至少有________条边。
13.101个顶点的连通网络N有100条边,其中权值为1, 2, 3, 4, 5, 6, 7, 8, 9, 10的边各
10条,则网络N的最小生成树各边的权值之和为_________。
14.在使用Kruskal算法构造连通网络的最小生成树时,只有当一条候选边的两个端点不在同一个
________上,才有可能加入到生成树中。
15.深度优先生成树的高度比广度优先生成树的高度________。
16.求解带权连通图最小生成树的Prim算法适合于________图的情形,而Kruskal算法适合于
________图的情形。
17.求解最短路径的Dijkstra算法适用于各边上的权值________的情形。
若设图的顶点数为n,则该
算法的时间复杂度为________。
18.若对一个有向无环图进行拓扑排序,再对排在拓扑有序序列中的所有顶点按其先后次序重新编号,则
在相应的邻接矩阵中所有________元素将集中到对角线以上。
参考答案: 1. 非空 2. 有, 无 3. n(n-1)/2, 0
4. n-1
5. 有
6. 2(n-1)
7. 4,V0V1V3V2(或V0V2V1V3, V0V2V3V1, V0V3V1V2)
8. PQRST和PRQTS 9. n-1 10. 2
11. 2 12. n-1 13. 550
14. 连通分量15. 高16. 稠密,稀疏
17. 非负,O(n2) 18. 非零(或值为1的)
三、判断题
1.一个图的子图可以是空图,顶点个数为0。
2.存储图的邻接矩阵中,矩阵元素个数不但与图的顶点个数有关,而且与图的边数也有关。
3.一个有1000个顶点和1000条边的有向图的邻接矩阵是一个稀疏矩阵。
4.对一个连通图进行一次深度优先搜索(depth first search)可以遍访图中的所有顶点。
5.有n (n≥1) 个顶点的无向连通图最少有n-1条边。
6.有n (n≥1) 个顶点的有向强连通图最少有n条边。
7.图中各个顶点的编号是人为的,不是它本身固有的,因此可以因为某种需要改变顶点的编号。
8.如果无向图中各个顶点的度都大于2,则该图中必有回路。
9.如果有向图中各个顶点的度都大于2,则该图中必有回路。
10.图的深度优先搜索(depth first search)是一种典型的回溯搜索的例子,可以通过递归算法求
解。
11.图的广度优先搜索(breadth first search)算法不是递归算法。
12.有n个顶点、e条边的带权有向图的最小生成树一般由n个顶点和n-1条边组成。
13.对于一个边上权值任意的带权有向图,使用Dijkstra算法可以求一个顶点到其它各个顶点的最短路
径。
14.对一个有向图进行拓扑排序(topological sorting),一定可以将图的所有顶点按其关键码大小
排列到一个拓扑有序的序列中。
15.有回路的有向图不能完成拓扑排序。
16.对任何用顶点表示活动的网络(AOV网)进行拓扑排序的结果都是唯一的。
17.用边表示活动的网络(AOE网)的关键路径是指从源点到终点的路径长度最长的路径。
18.对于AOE网络,加速任一关键活动就能使整个工程提前完成。
19.对于AOE网络,任一关键活动延迟将导致整个工程延迟完成。
20.在AOE网络中,可能同时存在几条关键路径,称所有关键路径都需通过的有向边为桥。
如果加速这样
的桥上的关键活动就能使整个工程提前完成。
21.用邻接矩阵存储一个图时,在不考虑压缩存储的情况下,所占用的存储空间大小只与图中的顶点个数
有关,而与图的边数无关。
22.邻接表只能用于有向图的存储,邻接矩阵对于有向图和无向图的存储都适用。
23.邻接矩阵只适用于稠密图(边数接近于顶点数的平方),邻接表适用于稀疏图(边数远小于顶点数的平
方)
24.存储无向图的邻接矩阵是对称的,因此只要存储邻接矩阵的下(上)三角部分就可以了。
25. 连通分量是无向图中的极小连通子图。
26. 强连通分量是有向图中的极大强连通子图。
27. 在AOE 网络中一定只有一条关键路径。
参考答案: 1. 否
2. 否
3. 是
4. 是
5. 是
6. 否
7. 是
8. 是
9. 否 10. 是 11. 是 12. 否 13. 否 14. 否 15. 是 16. 否 17. 是 18. 否 19. 是 20. 是 21. 是 22. 否 23. 是 24. 是
25. 否
26. 是
27. 否
四、运算题
1. 设连通图G 如图所示。
试画出该图对应的邻接矩阵表示,并给出对它执行从顶点V0开始的广度优先
搜索的结果。
2. 设连通图G 如图所示。
试画出该图及其对应的邻接表表示,并给出对它执行从V0开始的深度优先搜
索的结果。
3. 设连通图G 如图所示。
试画出从顶点V0出发的深度优先生成树,指出图G 中哪几个顶点是关节点(即
万一它失效则通信网络将发生故障)。
4. 设连通图G 如图所示,
(1) 如果有关节点,请找出所有的关节点。
(2) 如果想把该连通图变成重连通图,至少在图中加几条边?如何加?
V 4 6
V 4 6
V 4
6⑩ ① ② ③ ④ ⑤ ⑥ ⑦
⑧
⑨
1
n 0k kj
ik ij b a c -==
5. 对于如图所示的有向图,试写出:
(1) 从顶点①出发进行深度优先搜索所得到的深度优先生成树; (2) 从顶点②出发进行广度优先搜索所得到的广度优先生成树
6. 设有向图G 如图所示。
试画出从顶点V0开始进行深度优先搜索和广度优先搜索得到的DFS 生成森林
和BFS 生成森林。
7. 表示图的另一种方法是使用关联矩阵INC[ ][ ]。
其中,一行对应于一个顶点,一列对应于一条边。
因此,如果边j 依附于顶点i ,则INC[i][j]=1。
如果ADJ 是图G =(V, E )的邻接矩阵,INC 是关联矩阵,试说明在什么条件下将有ADJ = INC ⨯INCT -I ,其中,INCT 是矩阵INC 的转置矩阵,I 是单位矩阵。
两个n ⨯n 的矩阵的乘积C = A ⨯B 定义为
公式中的 定义为按位加,
定义为按位乘。
设无向图G 如图所示。
试画出该图的邻接矩阵和关联矩阵。
8. 设有一个连通网络如图所示。
试按如下格式,应用Kruskal 算法给出在构造最小生成树过程中顺序选出的各条边。
1 V 7
65
①
② ③ ④ ⑤
( 始顶点号,终顶点号, 权值 ) ( , , ) ( , , ) ( , , ) ( , , ) ( , , )
9. 设有一个连通网络如图所示。
试采用prim 算法从顶点0开始构造最小生成树。
(写出加入生成树顶点
集合S 和选择边Edge 的顺序)
10. 计算连通网的最小生成树的Dijkstra 算法可简述如下:将连通网所有的边以方便的次序逐条加入到
初始为空的生成树的边集合T 中。
每次选择并加入一条边时,需要判断它是否会与先前加入T
中的边构成回路。
如果构成了回路,则从这个回路中将权值最大的边退选。
如果以邻接矩阵作为连通网的存储结构(仅使用矩阵的上三角部分),并在邻接矩阵的下三角部分记录最小生成树的边信息。
试以如下所示的图G 为例,画出构造出最小生成树及其邻接矩阵,并在括号内填入每次选择的边和可能去掉的边。
选 择 的 边
去 掉 的 边 (顶点, 顶点,
权值)
(顶点, 顶
点,
权值) ( , , ) ( , , ) ( , , ) ( , , ) ( , , )
( , , )
26 21
11 ① ② ⑤ ④ ③ ⑥ 18 14 16 19
9 5 6 ⎪⎪⎪
⎪⎪⎪⎪⎪⎭
⎫
⎝⎛------------∞∞--∞-∞∞=02601118060199502114160Edge
( , , )( , , )
( , , )( , , )
( , , )( , , )
( , , )( , , )
( , , )( , , )
( , , )( , , )
( , , )( , , )
11.有八项活动, 每项活动要求的前驱如下:
(1) 试画出相应的AOV网络, 并给出一个拓扑排序序列。
(2) 试改变某些结点的编号, 使得用邻接矩阵表示该网络时所有对角线以下的元素全为0。
12.试对下图所示的AOE网络
(1) 这个工程最早可能在什么时间结束。
(2) 确定哪些活动是关键活动。
画出由所有关键活动构成的图,指出哪些活动加速可使整个工程提前完成。
13.设带权有向图如图所示。
试采用Dijkstra算法求从顶点0到其他各顶点的最短路径和最短路径长度。
14.一项工程由六个子工程p1, p2, , p6组成。
这些子工程之间有下列关系:p1 < p2, p3 < p6,
p4 < p3, p2 < p6, p4 < p5, p1 < p3, p5 < p6。
符号“<”表示“领先于”的关系。
例如,p2 < p6表示p2完成后p6才能开始。
试给出该工程的三种可能的施工顺序。
15.设一有向图如下所示,请问该有向图是否为强连通图,并画出该有向图所有的强连通分量。
参考答案:
1. 图G 对应的邻接矩阵为
⎥⎥⎥
⎥
⎥⎥
⎥
⎥⎥
⎥
⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣
⎡=001000000001001000110001000000000100000000010
011000111
000101001000011001000001110G.Edge
执行广度优先搜索的结果为V0V1V3V2V4V7V6V5V8,搜索结果不唯一。
2. 图G 对应的邻接表为:
执行深度优先搜索的结果为:V0V1V4V3V6V7V8V2V5,搜索结果不唯一。
3. 图G 中,从V0出发的深度优先生成树为:
图G 中的关节点为:V1, V2, V3, V6。
4. (1) 关节点为 ①, ②, ③, ⑦, ⑧
(2) 至少加四条边 (1, 10), (3, 4), (4, 5), (5, 6)。
从 ③ 的子孙结点⑩到③的祖先结点①引一条边,从 ② 的子孙结点 ④ 到根 ① 的另一分支 ③ 引一条边,并将 ⑦ 的子孙结点 ⑤、⑥ 与结点 ④ 连结起来,可使其变为重连通图。
(解答不唯一)
V 4
6
5. 以顶点 ① 为根的深度优先生成树(不唯一):
以顶点 ② 为根的广度优先生成树:
6. 深度优先生成森林为:
广度优先生成森林为:
7. 当图中的顶点个数等于边的条数时,ADJ = INC*INCT-I 成立。
图G 对应的邻接矩阵为:
7
6543
21001111000
10000100100001001000001010000010
0110000100011001000001107
6543210ADJ ⎥⎥
⎥
⎥⎥
⎥
⎥⎥
⎥
⎥⎥⎦
⎤⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡=
1
V 23
V 7 V 6 5
1 V 23
V 7
V 6 5①
② ③ ④ ⑤
①
②
③
④
⑤
①
②
③
④
⑤
对应的关联矩阵为:
8.应用Kruskal算法顺序选出最小生成树的各条边为:
( 始顶点号,终顶点号,权值 )
( 0, 3, 1 )
( 2, 5, 2 )
( 1, 4, 3 )
( 3, 5, 4 )
( 3, 4, 5 )
9.采用prim算法从顶点0开始构造最小生成树的过程:
10.最小生成树及其邻接矩阵如图所示
选择的边去掉的边
(顶点, 顶
点, 权值)
(顶点, 顶
点,
权值)
7
6
5
4
3
2
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
9
8
7
6
5
4
3
2
1
INC
⎥
⎥
⎥
⎥
⎥
⎥
⎥
⎥
⎥
⎥
⎥
⎦
⎤
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎢
⎣
⎡
=
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎪
⎭
⎫
⎝
⎛
-
-
-
-
-
-
-
-
-
∞
∞
-
∞
∞
∞
=
26
11
18
6
19
9
5
21
14
16
Edge
11
14
6
5
16
①②
④
③
⑥
14
16
5
6
11
( 2 ,
1 ,
16 ) ( , , ) ( 5 ,
1 ,
14 ) ( , , ) ( 6 ,
1 ,
21 ) ( , , ) ( 6 ,
2 ,
19 ) ( 6 , 1 , 21 ) ( 6 ,
4 ,
11 ) ( , , ) ( 6 ,
5 ,
26 ) ( 6 , 5 , 26 ) ( 5 ,
4 ,
18 ) ( 6 , 2 , 19 ) ( 4 ,
2 ,
9 ) ( 5 , 4 , 18 ) ( 3 ,
2 ,
5 ) ( , , ) ( 4 ,
3 ,
6 ) ( 4 , 2 , 9 )
选择顺序不唯一。
11. 相应的AOV 网络为:
一个拓扑排序序列为:A0,A1,A4,A2,A5,A3,A6,A7。
注意:拓扑排序结果不唯一。
按拓扑有序的次序对所有顶点从新编号:
相应邻接矩阵为:
A7
A7
7
6543
2100000000010000000010000001000000000110000
0001000000000100001010107
6543210⎥⎥
⎥
⎥⎥
⎥
⎥⎥
⎥
⎥⎥⎦
⎤⎢⎢⎢⎢⎢⎢⎢⎢
⎢⎢⎢⎣⎡=Edge
12. 针对下图所示的AOE 网络
各顶点(事件)的最早可能开始时间Ve(i)和最迟允许开始时间Vl(i)参看下表: 顶点 1 2 3 4 5 6 Ve 0 19 15 29 38 43 Vl
0 19 15 37 38 43
各边(活动)的最早可能开始时间Ee(k)和最迟允许开始时间El(k)参看下表: 边 <1,2> <1,3> <3,2> <2,5> <3,5> <2,4> <4,6> <5,6> Ee 0 0 15 19 15 19 29 38 El 17 0 15 19 27 27 37 38
如果活动k 的最早可能开始时间Ee(k) 与最迟允许开始时间El(k)相等,则该活动是关键活动。
本题的关键活动为<1,3>, <3,2>, <2,5>, <5,6>,它们组成关键路径。
这些关键活动中任一个提前完成,整个工程就能提前完成。
整个工程最早在43天完成。
由关键活动组成的AOV 网络如图所示。
13. 带权有向图如图所示:
应用Dijkstra 算法求从顶点V0到其他各顶点的最短路径Path 和最短路径长度Len 的步骤如下:
14. 图G 为 可能的施工顺序有:
p1, p2, p4, p3, p5, p6 p1, p4, p2, p3, p5, p6 p4, p5, p1, p3, p2, p6
15. 该图的强连通分量分别为:
五、算法分析题
1. 已知有向图的邻接矩阵表示及其一个算法描述如下:
p2
p6
const int MaxVertices = 5;
struct Graph { //图的邻接矩阵表示
int Edge[MaxVertices][MaxVertices]; //有向图邻接距阵
int CurrentNode; //有向图当前结点数
int CurrentEdges; //当前边数
}
int unknown ( int i ) {
int d = 0;
for ( int j = 0; j < CurrentNode; j++) {
if ( Edge[i][j] != 0 ) d++;
if ( Edge[j][i] != 0 ) d++;
}
return d;
}
(1)若定义图的一个对象Graph G,则执行操作G.unknown (3) 后的返回值是多少?
(2)试说明该算法的功能及时间复杂度。
2.已知有向图的邻接矩阵表示及其一个操作算法描述如下:
const int MaxVertices = 5;
struct Graph { //图的邻接矩阵表示
int Edge[MaxVertices][MaxVertices]; //有向图邻接距阵
int CurrentNode; //有向图当前结点数
int CurrentEdges; //当前边数
}
void unknown ( int i ) {
int d, j;
d = 0;
for ( j = 0; j < CurrentNode; j++ ) {
if ( Edge[i][j] ) { d++; Edge[i][j] = 0; }
if ( Edge[j][i] ) { d++; Edge[j][i] = 0; }
}
CurrentEdges -= d;
}
若定义图的一个对象Graph G,试写出执行操作G.unknown (3) 后该图的邻接矩阵,并说明该算法的功能。
3.已知有向图的邻接表类的表示的形式描述如下:
struct Edge { //邻接表中边结点的定义
int dest; //邻接的结点
float cost; //边的权值
Edge * link;
};
template <class Type> struct Vertex { //邻接表中顶点的定义Type data;
Edge *adj;
};
template <class Type> struct Graph { //邻接表
Vertex<Type> * NodeTable; //顶点表
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
int Degree[MaxVertices]; //各个顶点的度的记录数组}
//下列算法是计算有向图中各个顶点的度,并保存在数组Degree[ ]中。
请在处//填入合适的内容,使其成为一个完整的算法。
void FindDegree ( ) {
int i; Edge * p = NULL;
for ( i = 0; i < NumVertices; i++ ) Degree[i] = (1) ;
for ( i = 0; i < NumVertices; i++)
for ( p = NodeTable[i].adj; p != NULL; p = p->link ) {
(2) ;
(3) ;
}
};
4.已知有向图的邻接表类的表示的形式描述如下:
struct Edge { //邻接表中边结点的定义
int dest; //邻接的结点
float cost; //边的权值
Edge * link;
};
template <class Type> struct Vertex { //邻接表中顶点的定义Type data;
Edge *adj;
};
template <class Type> struct Graph { //邻接表
Vertex<Type> * NodeTable; //顶点表
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
int Degree[MaxVertices]; //各个顶点的度的记录数组}
//下列算法是计算有向图G中一个顶点vi的入度。
请在处填入合适的内容,//使其成为一个完整的算法。
void FindDegree ( int i ) {
int deg, j; Edge * p = NULL;
deg = 0;
for ( j = 0; j < NumVertices; j++ ) {
p = NodeTable[j].adj;
while ( (1) ) {
p = p->link;
if ( p == NULL ) break;
}
if ( p != NULL ) (2) ;
}
return deg;
}
5.已知有向图的邻接表类的表示的形式描述如下:
struct Edge { //邻接表中边结点的定义
int dest; //邻接的结点
float cost; //边的权值
Edge * link;
};
template <class Type> struct Vertex { //邻接表中顶点的定义Type data;
Edge *adj;
};
template <class Type> struct Graph { //邻接表
Vertex<Type> * NodeTable; //顶点表
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
int Degree[MaxVertices]; //各个顶点的度的记录数组}
//下列算法是从有向图G中删除所有以vi为弧头的有向边。
请在处填入合适//的内容,使其成为一个完整的算法。
void DeletEdge ( int i ) {
int de = 0, j; Edge *p, *q;
if ( i >= NumVertices )
{ cout << "错误输入" << endl; exit (1); }
for ( j = 0; j < NumVertices; j++ ) {
p = NodeTable[j].adj;
while ( (1) )
{ q = p; p = p->link; }
if ( p != NULL ) {
if ( p != NodeTable[j].adj ) q->link = p->link;
else (2) ;
delete p;
de++;
}
}
NumEdges = NumEdges - de;
}
6.已知带权图的邻接矩阵表示和邻接表类表示的形式描述分别如下:
(1)邻接矩阵的定义
#define INFINITY INT_MAX //INT_MAX为最大整数,表示∞const int MaxVertices = 20;
template <class Type> struct AdjMatrix {
Type * NodeTable; //顶点表定义
float arr[Maxvertices][MaxVertices]; //邻接矩阵定义
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
};
(2) 邻接表定义
struct Edge { //邻接表中边结点的定义int dest; //邻接的结点
float cost; //边的权值
Edge * link;
};
template <class Type> struct Vertex { //邻接表中顶点的定义Type data;
Edge *adj;
};
template <class Type> struct AdjTable { //邻接表
Vertex<Type> * NodeTable; //顶点表
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
}
//下列算法是根据一个图的邻接矩阵建立该图的邻接表,请在处填入合适
//的内容,使其成为一个完整的算法。
AdjTable<Type> * convertM ( ) {
//将图的邻接矩阵(用this指针指示)转换为邻接表,函数返回邻接表的地址。
AdjTable<Type> * A; Edge *e;
A->NodeTable = new Vertex<Type>[NumVertices];
A->NumEdges = NumEdges;
A->NumVertices = NumVertices;
for ( int i = 0; i < NumVertices; i++ ) {
A->NodeTable[i].data = NodeTable[i];
A->NodeTable[i].adj = (1) ;
for ( int j = 0; j < NumVertices; j++ )
if ( arr[i][j] != INFINITY && arr[i][j] != 0 ) {
e = new Edge;
e->dest = j;
e->cost= (2) ;
e->link = A->NodeTable[i].adj;
(3) ;
}
}
return A;
}
7.已知带权图的邻接矩阵表示和邻接表类表示的形式描述分别如下:
(1) 邻接矩阵的定义
#define INFINITY INT_MAX //INT_MAX为最大整数,表示∞
const int MaxVertices = 20;
template <class Type> struct AdjMatrix {
Type * NodeTable; //顶点表定义
float arr[Maxvertices][MaxVertices]; //邻接矩阵定义
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
};
(2) 邻接表定义
struct Edge { //邻接表中边结点的定义int dest; //邻接的结点
float cost; //边的权值
Edge * link;
};
template <class Type> struct Vertex { //邻接表中顶点的定义Type data;
Edge *adj;
};
template <class Type> struct AdjTable { //邻接表
Vertex<Type> * NodeTable; //顶点表
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
}
//下列算法是根据一个图的邻接表存储结构建立该图的邻接矩阵存储结构,
//请在处填入合适的内容,使其成为一个完整的算法
AdjMatrix<Type> * convertAL( ) {
//将图的邻接表(用this指针指示)转换为邻接矩阵,函数返回邻接矩阵的地址。
AdjMatrix<Type> * A; int i, j; Edge *p;
A->NodeTable = new Vertex<Type>[NumVertices];
A->arr = new float [Maxvertices][MaxVertices];
A->NumEdges = NumEdges;
A->NumVertices = NumVertices;
for ( i = 0; i < NumVertices; i++ ) {
for ( j = 0; j < NumVertices; j++ ) A->arr[i][j] = INFINITY;
A->NodeTable[i] = _______ __(1)___ ______;
}
for ( i = 0; i < NumVertices; i++ ) {
p = NodeTable[i].adj;
while ( p != NULL ) {
A->arr[i][p->dest] = ___ __(2)__________;
________________(3)________________;
}
}
}
8.已知图的邻接表和逆邻接表的形式描述如下:
struct Edge { //结点定义
int dest; //邻接结点
float cost; //边的权值
Edge * link;
};
template <class Type> struct Vertex { //顶点定义
Type data;
Edge *adj;
};
template<class Type> struct Graph { //邻接表与逆邻接表定义
Vertex<Type> * NodeTable; //邻接表顶点表
Vertex<Type> * OppositNodeTable; //逆邻接表顶点表
int NumVertices; //当前顶点个数
int NumEdges; //当前边数
}
//下列算法是根据一个图的邻接表存储结构建立该图的逆邻接表存储结构,请
//在处填入合适的内容,使其成为一个完整的算法。
void convertM ( ) {
int i; Edge *p, *q;
OppositNodeTable = new Vertex<Type>[NumVertices];
for ( i = 0; i < NumVertices; i++ ) {
OppositNodeTable[i].data = NodeTable[i].data;
OppositNodeTable[i].adj = NULL;
}
for ( i = 0; i < NumVertices; i++ ) {
p = NodeTable[i].adj;
while ( p != NULL ) {
q = new Edge;
q->dest = i;
q->cost = p->cost;
_________ ____(1)____ _________;
OppositNodeTable[p->dest].adj = q;
______________(2)_____________;
}
}
}
参考答案:
1.(1) 执行操作后的返回值是5。
//2分
(2) 算法的功能是计算有向图中一个顶点的度。
//2分
算法的时间复杂度是O(n),n为图的顶点个数。
//2分
2.执行操作G.unknown (3) 后,图的邻接矩阵为://3分
算法的功能是从图中删除所有与某个顶点相关的边。
//3分
3.填空结果
(1) 0 //2分
(2) Degree[p->dest]++ //2分
(3) Degree[i]++ //2分 ( 注:(2), (3)互换也正确 )
4.填空结果
(1) p != NULL && p->dest != i //3分
(2)deg++; //3分
5.填空结果
(1) p != NULL && p->dest != i //3分
(2) NodeTable[j].adj = p->link; //3分
6.填空结果
(1) NULL //2分
(2) arr[i][j] //2分
(3) A->NodeTable[i].adj = e //2分
7.填空结果
(1) NodeTable[i].data //2分
(2) p->cost //2分
(3) p = p->link //2分
8.填空结果
(1) q->link = OppositNodeTable[p->dest].adj //3分
(2) p = p->link //3分
六、算法设计题
1.试编写函数用邻接表存储结构实现
template<class Type> int AdjTable <Type>::GetFirstNeighbor ( int v );
//给出顶点位置为v 的第一个邻接顶点的位置,如果找不到,则函数返回-1
2.用邻接表存储结构实现带权有向图的构造函数
template <class Type> AdjTable <Type>:: AdjTable ( int sz = DefaultSize ) : MaxVertices(sz) { ……输入顶点个数、数据及各条边的信息,建立邻接表…… }
3.试编写函数用邻接表存储结构实现
template<class Type> int AdjTable <Type>::GetNextNeighbor ( int v, int w );
//给出顶点v的邻接顶点w的下一个邻接顶点的位置,若没有下一个邻接顶点,则函数返回-1
参考答案
1.算法实现如下
template<class Type> int AdjTable <Type>::GetFirstNeighbor ( int v ) { //给出顶点位置为v 的第一个邻接顶点的位置,如果找不到,则函数返回-1
if ( v != -1 ) {
Edge *p = NodeTable (v).adj; //4分
if ( p != NULL ) return p->dest; //4分
}
return –1;
}
2.算法实现如下
template <class Type> AdjTable <Type>::AdjTable ( int sz = DefaultSize ) : MaxVertices ( sz ) {
int i, k, j; Type tail, head; float weight; Edge *p;
NodeTalbe = new Vertex<Type>[MaxVertices];
cin >> NumVertices;
for ( i = 0; i < NumVertices; i++ ) { //4分
cin >> NodeTable[i].data;
NodeTable[i].adj = NULL;
}
cin >> NumEdges;
for ( i = 0; i < NumEdges; i++ ) { //4分
cin >> tail >> head >> weight;
k = GetVertexPos(tail); j = GetVertexPos(head);
p = new Edge;
p->dest = j; p->cost = weight;
p->link = NodeTable[k].adj; NodeTable[k].adj = p;
}
}
3.算法实现如下
template <class Type> int AdjTable <Type>::GetNextNeighbor ( int v, int w ) {
//给出顶点v的邻接顶点w的下一个邻接顶点的位置,若没有下一个邻接顶点,则
//函数返回-1
if ( v != -1 ) {
Edge * p = NodeTable[v].adj;
while ( p != NULL )
if (p->dest == w && p->link != NULL ) return p->link->dest;
else p = p->link;
}
return –1;
}。