图的遍历及生成树
离散数学中的图的树与生成树的计数

在离散数学中,图是一个由点和边组成的抽象数学模型。
其中,树是一种特殊的图,它是一个无环连通图。
在图论中,树扮演了重要的角色,它具有许多有趣的性质和应用。
而生成树则是树的一个特殊子集,它由给定图中的所有顶点和部分边构成。
本文将介绍图的树的基本概念,并探讨生成树的计数方法。
首先,让我们来看看图的树。
树是一种无环连通图,其中任意两个顶点之间存在唯一一条路径。
它具有以下性质:1.n个顶点的树有n-1条边。
这可以通过归纳法证明:当n=1时,结论成立;假设n=k时成立,那么n=k+1时,只需要添加一个顶点和一条边,即可构成n=k+1个顶点的树。
因此,结论成立。
2.连接树上任意两个顶点的边都是桥。
即如果一条边被删除,那么树就会变成两个或更多个不相连的子树。
3.树是一个高度平衡的结构。
对于一个n个顶点的树,任意两个叶子结点之间的路径长度至多相差1。
4.树的任意两个顶点之间有唯一一条路径,路径长度为顶点之间的边数。
接下来,让我们来讨论生成树的计数方法。
生成树是树的一个特殊子集,它是由给定图中的所有顶点和部分边构成。
生成树的计数在图论中具有重要的意义和应用。
对于一个具有n个顶点的连通图来说,其生成树的个数可以通过Cayley公式计算得到。
Cayley公式是由亚瑟·凯利于1889年提出的,它给出了完全图的生成树数目。
据此,我们可以得到生成树的计数公式为:T = n^(n-2),其中T表示生成树的个数。
此外,还有一种常见的计数方法是基于度数矩阵和邻接矩阵的矩阵树定理。
矩阵树定理由高斯于1847年提出,它提供了一种计算图的生成树个数的方法。
根据矩阵树定理,一个无向图G的生成树数目等于该图度数矩阵的任意一个(n-1)阶主子式的行列式的值。
其中,度数矩阵是一个对角矩阵,它的对角线上的元素为各个顶点的度数。
邻接矩阵则是一个关于顶点间连接关系的矩阵,其中1表示相邻顶点之间存在边,0表示不存在边。
除了数学方法,还存在一种基于图的遍历的计数方法,称为Kirchhoff矩阵树定理。
第15讲图的遍历

V6
V8
V8
V7
V5 深度优先生成树
V8 V1
V2
V3
V4 V5 V6 V7
V8 广度优先生成树
27
例A
B
CD E
F
GH
I
K
J
L
M
A
D
G
LCF
KI E
H M
JB
深度优先生成森林
28
二、图的连通性问题
▪1、生成树和生成森林
▪ 说明
G
▪ 一个图可以有许多棵不同的生成树
KI
▪ 所有生成树具有以下共同特点:
g.NextAdjVex(v, w))
{
if (g.GetTag(w) == UNVISITED)
{
g.SetTag(w, VISITED);
g.GetElem(w, e);
Visit(e);
q.InQueue(w);
}
}}}
24
一、图的遍历 两种遍历的比较
V0
V1 V4
V0
V1 V4
V3
V2 V5
16
一、图的遍历
广度优先遍历序列?入队序列?出队序列?
V1
V2
V3
V1
V4
V5 V6
V7
V8
遍历序列: V1
17
一、图的遍历
广度优先遍历序列?入队序列?出队序列?
V1
V2
V3
V2 V3
V4
V5 V6
V7
V8
遍历序列: V1 V2 V3
18
一、图的遍历
广度优先遍历序列?入队序列?出队序列?
V1
V2
图的遍历及生成树

• •邻接表的DFS算法
void DFS(ALGraph G, int v) { ArcNode *p;
visited[v] = 1; /*置已访问标记*/ printf("%d ", v); /*输出被访问顶点的编号*/ p = G.vertices[v].firstarc; /*p指向顶点v的第一个邻接点*/ while (p!=NULL) {
•v11
•v1,
•v2
•v3
•v2,
•v4,
•v5
•v8,
•v4
•v6
•v7
•v5,
•v3,
•v8
•v6,
•v7
•
•图的DFS算法一般描述
•int visited[MAXVEX]; //访问标志数组
•void DFSTraverse(Graph G)
•{ //对图G作深度优先遍历
• for( v=0; v<G.vexnum; ++v ) visited[v]=FALSE;
•} // DFS1
•G.arcs[v][j] =1
•有邻接点
•visited [n]=0
•未访问过
•
分析:
在遍历图时,对图中每个顶点至多调用一次DFS函数 ,因为一旦某个顶点被标志成已被访问,就不再从它出发 进行搜索。
因此,遍历图的过程实质上是对每个顶点查找其邻接 点的过程。其耗费的时间则取决于所采用的存储结构。 如果用邻接矩阵来表示图,遍历图中每一个顶点都要从 头扫描该顶点所在行,因此遍历全部顶点所需的时间为 O(n2)。 如果用邻接表来表示图,虽然有 2e 个表结点,但只需扫 描 e 个结点即可完成遍历,加上访问 n个头结点的时间, 因此遍历图的时间复杂度为O(n+e)。
graph

割顶: 连通图中的一个点,如果删去这个点和相关的边, 那么整个图就不再连通了。 (这里只讨论无向图中的桥和割顶) B A F E C D
在左图中,DE之间的边即为这张图中唯 一的一个桥。
而D,E则分别为这张图中的两个割顶。
G
桥和割顶
A B
A
F E C D G C D
B
E F
在dfs树中,我们不难发现,对于一个桥,必 然没有一条返祖边跨越这条边,反之,则必然 存在一条返祖边跨越这条边。
}
例2、phoneline (USACO)
有N(1<=n<=1000)个点,M(1<=m<=10000)条边, 寻找一条从结点1到结点N的路径,使得其中各 边长度的最大值最小。并且给定一个整数 K(0<=k<=300),可以使路径中的K条边长度变为 零。求最小的那个最大值。 乍看和最短路没有关系,因为要求最大值最小。
时间复杂度同最短路径
Sec.3 最小生成树
最小生成树的定义:对于一个连通的带权图,选取一些边,使 得整个图连通,并且所选边的权值和最小。这些边与点所构成 的集合就是最小生成树。
3
4 4
3
NOIP信息学竞赛初赛-图论算法基础-专题十一-1

专题十一:图论算法基础对于图论算法,NOIP初赛不要求会实现算法,但手工操作还是要会的,复赛是要求会代码实现的。
什么是图一个图是一个序偶<V, E>,记为G =<V, E> 。
V 为顶点集, E 为V 中结点之间的边的集合。
自环:一条边的两个端点是相同的。
重边:两个端点之间有两条以上的边,称他们是重边。
简单图:没有自环和重边的图。
无向边:边是双向的。
有向边:单向边,有箭头。
无向图:只有无向边的图。
有向图:只有有向边的图。
混合图:既有无向边又有有向边。
顶点的度:无向图中,一个顶点相连的边数称为该顶点的度;有向图中,从一个顶点出发的边数称为该顶点得出度;到达该顶点的边数称为它的入度。
图论基本定理:著名的握手定理。
无向图中结点度数的总和等于边数的两倍。
有向图中结点入度的和等于出度的和等于边数。
通路:给定图G中结点和边交替出现的一个序列:v0 e1 v1 e2 v2 …ek vk,若每条边ei的两端点是vi-1 和vi ,那么称该序列是从v0到vk的一条通路。
基本通路(路径):没有重复出现的结点的通路。
图的连通性:若一张无向图的任意两个结点之间都存在通路,那么称该图是连通的。
连通分量:图中连通的顶点与边的集合。
权和网:在图的边给出相关的数,成为权。
权可以表示一个顶点到另一个顶点的距离,耗费等。
带权图一般成为网。
最短路径:对于一张不带权的无向图来说,从s到t的最短路径就是所有从s到t的通路中长度最短的那一条(可能不唯一),通路上的边数称为路径的长度。
完全图:任何两个顶点之间都有边(弧)相连称为完全图。
稀疏图、稠密图:边(弧)很少的图称为稀疏图,反之为稠密图。
图的存储:邻接矩阵在邻接矩阵表示中,除了存放顶点本身信息外,还用一个矩阵表示各个顶点之间的关系。
若(i,j)∈E(G)或〈i,j〉∈E(G),则矩阵中第i行第j列元素值为1,否则为0 。
例如, 下面为两个无向图和有向图对应的邻接矩阵。
七图

n图的基本概念n图的存储结构n图的遍历与连通性n最小生成树n最短路径n活动网络7.1图的基本概念n图定义图是由顶点集合(vertex)及顶点间的关系集合组成的一种数据结构:Graph=( V, E )其中V= { x| x ∈某个数据对象}是顶点的有穷非空集合;E= {(x, y) |x, y ∈V }或E= {<x, y>|x, y ∈V&& Path(x, y)}是顶点之间关系的有穷集合,也叫做边(edge)集合。
Path(x, y)表示从x 到y 的一条单向通路, 它是有方向的。
n有向图与无向图在有向图中,顶点对<x, y>是有序的。
在无向图中,顶点对(x, y)是无序的。
n完全图若有n 个顶点的无向图有n(n-1)/2 条边, 则此图为完全无向图。
有n 个顶点的有向图有n(n-1) 条边, 则此图为完全有向图。
邻接顶点如果(u, v) 是E(G) 中的一条边,则称u 与v 互为邻接顶点。
n权某些图的边具有与它相关的数,称之为权。
这种带权图叫做网络。
n 子图设有两个图G =(V ,E )和G ,=(V ,,E ,)。
若V ,⊆V 且E,⊆E ,则称图G ,是图G 的子图。
n顶点v 的入度是以v 为终点的有向边的条数, 记作ID(v ); n顶点v 的出度是以v 为始点的有向边的条数, 记作OD(v )。
n 在有向图中, 顶点的度等于该顶点的入度与出度之和。
n 路径在图G =(V , E ) 中, 若从顶点v i 出发, 沿一些边经过一些顶点v p 1, v p 2, …, v pm ,到达顶点v j 。
则称顶点序列( v i v p 1 v p 2 ... v pm v j )为从顶点v i 到顶点v j 的路径。
它经过的边(v i , v p 1)、(v p 1, v p 2)、...、(v pm ,v j )应是属于E 的边。
n 路径长度u 非带权图的路径长度是指此路径上边的条数。
生成树算法的三个步骤
生成树算法的三个步骤生成树是图论中的重要概念,它描述了一个连通图的一个子图,该子图包含了图中的所有顶点,并且是无环的。
生成树算法是用来找到一个连通图的生成树的一种方法。
本文将介绍生成树算法的三个步骤:图的遍历、边的选择和生成树的构建。
一、图的遍历图的遍历是生成树算法的第一步,它的目的是将图中的所有顶点访问一遍。
常用的图的遍历算法有深度优先搜索(DFS)和广度优先搜索(BFS)。
深度优先搜索是通过递归的方式进行遍历,从某个顶点开始,先访问它的一个邻接顶点,然后再递归地访问该邻接顶点的邻接顶点,直到所有顶点都被访问过。
广度优先搜索是通过队列的方式进行遍历,从某个顶点开始,先访问它的所有邻接顶点,然后再依次访问这些邻接顶点的邻接顶点,直到所有顶点都被访问过。
二、边的选择边的选择是生成树算法的第二步,它的目的是选择一些边,使得这些边构成一个连通图的生成树。
常用的边的选择算法有最小生成树算法和最大生成树算法。
最小生成树算法的目标是选择一些边,使得这些边的权值之和最小。
常用的最小生成树算法有普里姆算法和克鲁斯卡尔算法。
普里姆算法是从一个顶点开始,每次选择一条最小权值的边,将该边连接的顶点加入到生成树中,直到所有顶点都被加入到生成树中。
克鲁斯卡尔算法是先将所有边按照权值从小到大排序,然后依次选择权值最小的边,如果这条边连接的两个顶点不在同一个连通分量中,则将这条边加入到生成树中。
最大生成树算法的目标是选择一些边,使得这些边的权值之和最大。
常用的最大生成树算法有逆克鲁斯卡尔算法和逆普里姆算法。
逆克鲁斯卡尔算法和逆普里姆算法的原理与克鲁斯卡尔算法和普里姆算法相反。
三、生成树的构建生成树的构建是生成树算法的第三步,它的目的是根据选择的边构建一个生成树。
生成树可以用邻接矩阵或邻接表来表示。
邻接矩阵是一个二维数组,其中的元素表示两个顶点之间是否有边。
邻接表是一种链表的数据结构,其中的每个节点表示一个顶点,节点的值表示该顶点的邻接顶点。
离散数学中的图论基础知识讲解
离散数学中的图论基础知识讲解图论是离散数学中的一个重要分支,研究的是图的性质和图中的关系。
图论在计算机科学、网络科学、运筹学等领域有着广泛的应用。
本文将从图的基本概念、图的表示方法、图的遍历算法以及一些常见的图论问题等方面进行讲解。
一、图的基本概念图是由顶点和边组成的一种数学结构。
顶点表示图中的元素,边表示元素之间的关系。
图可以分为有向图和无向图两种类型。
1. 无向图:无向图中的边没有方向,表示的是两个顶点之间的无序关系。
如果两个顶点之间存在一条边,那么它们之间是相邻的。
无向图可以用一个集合V表示顶点的集合,用一个集合E表示边的集合。
2. 有向图:有向图中的边有方向,表示的是两个顶点之间的有序关系。
如果从顶点A到顶点B存在一条有向边,那么A指向B。
有向图可以用一个集合V表示顶点的集合,用一个集合E表示有向边的集合。
二、图的表示方法图可以用多种方式进行表示,常见的有邻接矩阵和邻接表两种方法。
1. 邻接矩阵:邻接矩阵是一个二维数组,其中的元素表示两个顶点之间是否存在边。
如果顶点i和顶点j之间存在边,那么矩阵的第i行第j列的元素为1;否则为0。
邻接矩阵适用于表示稠密图,但对于稀疏图来说,会造成空间浪费。
2. 邻接表:邻接表是一种链表的数据结构,用来表示图中的顶点和边。
每个顶点对应一个链表,链表中存储与该顶点相邻的顶点。
邻接表适用于表示稀疏图,节省了存储空间。
三、图的遍历算法图的遍历是指按照某一规则访问图中的所有顶点。
常见的图的遍历算法有深度优先搜索(DFS)和广度优先搜索(BFS)。
1. 深度优先搜索:深度优先搜索是一种递归的搜索算法。
从某个顶点出发,首先访问该顶点,然后递归地访问与它相邻的未访问过的顶点,直到所有的顶点都被访问过。
2. 广度优先搜索:广度优先搜索是一种迭代的搜索算法。
从某个顶点出发,首先访问该顶点,然后依次访问与它相邻的所有未访问过的顶点,再依次访问与这些顶点相邻的未访问过的顶点,直到所有的顶点都被访问过。
数据结构实验报告及心得体会
数据结构实验报告及心得体会一、引言数据结构是计算机科学中的重要基础课程,通过实验环节的学习,我们能够更好地掌握和应用数据结构的概念、算法和操作。
本报告旨在总结和分享我们进行的数据结构实验,并提出相应的心得体会。
二、实验一:线性表的实现与应用1. 实验目的本实验旨在通过实现和应用线性表的基本操作,掌握线性表的存储结构和算法。
2. 实验内容我们选择了顺序表和链表两种线性表的实现方式,并实现了插入、删除和查找等基本操作。
通过实验,我们发现顺序表适用于元素个数较少、频繁查找的情况,而链表适用于插入和删除操作较多、元素个数不确定的情况。
3. 实验心得通过实验一,我们深刻认识到数据结构的不同实现方式对算法的影响。
选择合适的数据结构可以提高算法效率,提高程序的性能。
同时,我们也意识到了在实际应用中,根据问题的具体特点选择不同的数据结构才能得到最优解。
三、实验二:栈与队列的应用本实验旨在通过实现和应用栈和队列的基本操作,掌握栈和队列的特性及其在实际应用中的作用。
2. 实验内容我们分别实现了顺序栈、链式栈、顺序队列和链式队列,并实现了入栈、出栈、入队和出队等基本操作。
我们发现栈适用于实现回溯算法、递归算法等,而队列适用于广度优先搜索、线程池等场景。
3. 实验心得通过实验二,我们进一步理解了栈和队列在实际编程中的运用。
它们提供了方便的数据结构,帮助我们解决了许多实际问题。
同时,实验过程中,我们也发现了栈溢出的问题,意识到了合理管理栈空间的重要性。
四、实验三:树与二叉树的实现与应用1. 实验目的本实验旨在通过实现和应用树和二叉树的基本操作,掌握树和二叉树的存储结构和算法。
2. 实验内容我们实现了树和二叉树的基本操作,包括创建、插入、删除和遍历等。
通过实验,我们发现树在表示具有部分层次结构的问题时更合适,而二叉树在表示递归结构时更加方便。
通过实验三,我们深入理解了树和二叉树的特性及其应用。
树和二叉树是许多高级数据结构的基础,熟练掌握它们的操作对于解决实际问题非常重要。
图的遍历算法实验报告
图的遍历算法实验报告
《图的遍历算法实验报告》
在计算机科学领域,图的遍历算法是一种重要的算法,它用于在图数据结构中
访问每个顶点和边。
图的遍历算法有两种常见的方法:深度优先搜索(DFS)
和广度优先搜索(BFS)。
在本实验中,我们将对这两种算法进行实验,并比较
它们的性能和应用场景。
首先,我们使用深度优先搜索算法对一个简单的无向图进行遍历。
通过实验结
果可以看出,DFS算法会首先访问一个顶点的所有邻居,然后再递归地访问每
个邻居的邻居,直到图中所有的顶点都被访问到。
这种算法在一些应用场景中
非常有效,比如寻找图中的连通分量或者寻找图中的环路。
接下来,我们使用广度优先搜索算法对同样的无向图进行遍历。
通过实验结果
可以看出,BFS算法会首先访问一个顶点的所有邻居,然后再按照距离递增的
顺序访问每个邻居的邻居。
这种算法在一些应用场景中也非常有效,比如寻找
图中的最短路径或者寻找图中的最小生成树。
通过对比实验结果,我们可以发现DFS和BFS算法各自的优势和劣势。
DFS算
法适合用于寻找图中的连通分量和环路,而BFS算法适合用于寻找最短路径和
最小生成树。
因此,在实际应用中,我们需要根据具体的需求来选择合适的算法。
总的来说,图的遍历算法是计算机科学中非常重要的算法之一,它在许多领域
都有着广泛的应用。
通过本次实验,我们对DFS和BFS算法有了更深入的了解,并且对它们的性能和应用场景有了更清晰的认识。
希望通过这篇实验报告,读
者们也能对图的遍历算法有更深入的理解和认识。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
它未被访问的邻接顶点: 2.1 如果有,则访问此顶点,之后再从此顶点出发,返回
第1)步的操作; 2.2 如果没有,就再退回一步进行搜索。 2.3 重复上述过程,直到连通图中所有顶点都被访问过为
止。
例:从顶点v1出发,DFS下图。 v1
连通图:仅需从图中任一顶点出发,进行深度优 先搜索(或广度优先搜索),便可访问到图中所 有顶点。
非连通图:需从多个顶点出发进行搜索,而每一 次从一个新的起始点出发进行搜索过程中得到的顶 点访问序列恰为其各个连通分量中的顶点集。
基本概念
生成树:某连通分量的极小连通子图,它含有图中 全部顶点,但只有n-1条边 ;
期末考试
长春工业大学 >> 数据结构精品课程网站 >> 习题解析 /sjjg/index.php?option=com_co
ntent&task=category§ionid=&id=21&Itemid=266
7.3 图的遍历
从图中某一顶点出发访遍图中其余顶点,且使 每一个顶点仅被访问一次。这一过程就叫做图的 遍历。
2010-3-3
精品课件!
2010-3-3
精品课件!
作业
基于邻接矩阵的DFS算法实现 基于邻接矩阵的BFS算法实现
while (!QueueEmpty(Q)) { DeQueue(Q, u); // 队头元素出队并置为u for (w=FirstAdjVex(G,u); w>=0; w=NextAdjVex(G,u,w)) if ( ! visited[w]){ //w为u的尚未访问的邻接顶点 visited[w] = TRUE; Visit(w); EnQueue(Q, w); } //if
例: 0
起点 1 2 3
辅助数组 visited [n]
00 1 1 1 1 10 0 1 1 1 20 0 0 1 1 30 0 0 0 1
DFS 结果
v0 →v1 →v2 →v3
注意:在邻接表中,并非每个 链表元素(表结点)都被扫描 到, 因此遍历速度很快。
邻接表的DFS算法
void DFS(ALGraph G, int v) { ArcNode *p;
p = p->nextarc; /*p指向顶点v的下一个邻接点*/ } }
邻接矩阵的DFS算法
DFS1(MGraph G, int v)
{ //G.arcs[n][n]为邻接矩阵,v为起始顶点(编号)
visit(v);
//访问(例如打印)顶点v
visited[v]=1;
//访问后立即修改辅助数组标志
} //while }//if } // BFSTraverse
分析: 每个顶点至多进一次队列。遍历图的过程实质
上是通过边或弧找邻接点的过程,因此广度优先 搜索遍历图的时间复杂度和深度优先搜索遍历相 同,两者不同之处仅仅在于对顶点访问的顺序不 同。
邻接矩阵:O(n2) 邻接表:O(n+e)
第7章 图
visited[v] = 1; /*置已访问标记*/ printf("%d ", v); /*输出被访问顶点的编号*/ p = G.vertices[v].firstarc; /*p指向顶点v的第一个邻接点*/ while (p!=NULL) {
if (visited[p->adjvex]==0) DFS(G, p->adjvex); /*若p->adjvex顶点未访问,递归访问它*/
(2)若此时图中尚有顶点未被访问,则另选图 中一个未曾被访问的顶点作起始点;
(3)重复上述两步,直至图中所有顶点都被访 问到为止。
与树的先序遍历过程类似
详细过程:
1) 1.1 在访问图中某一起始顶点 v 后,由 v 出发,访问它的 任一邻接顶点 w1;
1.2 再从 w1 出发,访问与 w1邻接但还未被访问过的顶点 w2; 1.3 然后再从 w2 出发,进行类似的访问…… 直至到达所有
for( j=0; j<G.vexnum; j++) //从v所在行从头搜索邻接点
if ( G.arcs[v][ j] && ! visited[j] ) DFS1(G, j);
} // DFS1
G.arcs[v][j] =1
有邻接点
visited [n]=0
未访问过
分析:
在遍历图时,对图中每个顶点至多调用一次DFS函数, 因为一旦某个顶点被标志成已被访问,就不再从它出发进 行搜索。
2.广度优先搜索(BFS, Breadth_First 基S本ea思rc想h:)
从图中某个顶点V0出发,并在访问此顶点后依次 访问V0的所有未被访问过的邻接点,之后按这些顶 点被访问的先后次序依次访问它们的邻接点,直至
图中所有和V0有路径相通的顶点都被访问到; 若此时图中尚有顶点未被访问,则另选图中一个
1 v2
2 v3
3 v4 4 v5 5 v6 6 v7 7 v8
21
32 ^
0
3
4^
0
5
6^
1
7^
1
7^
2
6^
2
5^
3 4^
BFS非递归算法
void BFSTraverse(Graph G, Status (*Visit)(int v)){ //使用辅助队列Q和访问标志数组visited[v] for (v=0; v<G.vexnum; ++v) visited[v] = FALSE; InitQueue(Q); // 置空的辅助队列Q for ( v=0; v<G.vexnum; ++v ) if ( !visited[v]) { // v尚未访问 visited[v] = TRUE; Visit(v); EnQueue(Q, v); // v入队
抽象操作,可以是对结点进行的各种 处理,这里简化为输出结点的数据。
图的遍历操作要解决的关键问题
1、 在图中,如何选取遍历的起始顶点?
解决方案:从编号小的顶点开始 。
在图中,任何两个顶点之间都可能存在边,顶点是没 有确定的先后次序的,所以,顶点的编号不唯一。 这里指按顶点的存储顺序。
2、 因图中可能存在回路,在访问完某个顶点之后会沿 着某些边又回到了曾经访问过的顶点。那么如何避免顶 点的重复访问?
if (!visited[w]) DFS(G,w); }
用邻接表实现图的深度优先搜索
v1 v2
v5 v4
v8
v3
v6 v7 v9 v10
01 12 23 34 45 56 67 78 89 9 10
21
23 ^
0
3
4^
0
5
6^
1
7^
1
7^
2
6^
2
5^
3
4^
9 /\
8 /\
在图的邻接表中如何进行DFS? —照样借用visited [n ]
因此,遍历图的过程实质上是对每个顶点查找其邻接 点的过程。其耗费的时间则取决于所采用的存储结构。
如果用邻接矩阵来表示图,遍历图中每一个顶点都要从 头扫描该顶点所在行,因此遍历全部顶点所需的时间为 O(n2)。 如果用邻接表来表示图,虽然有 2e 个表结点,但只需扫 描 e 个结点即可完成遍历,加上访问 n个头结点的时间, 因此遍历图的时间复杂度为O(n+e)。
思考2:若对非连通图进行遍历,得到的是什么? 得到的将是各连通分量的生成树,即图的生成森林。
生成树
V1
V2
V3
V1
V2
V3
V4
V5 V6
V7
V4
V5 V6
V7
V8
(a)深度优先生成树
V8
(b) 广度优先生成树
例:求下图的深度优先生成树和广度优先生成树。
v1
v2
v5 v4
v3
v6
v7
v8
对非连通图,每个连通分量中的顶点集和遍历时走过的 边一起构成若干棵生成树,这些连通分量的生成树组成非 连通图的生成森林。 例:
7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图及其应用 7.6 最短路径
7.4 图的连通性问题
1)无向图的连通分量和生成树 2)最小生成树
普里姆算法 克鲁斯卡尔算法
1.无向图的连通分量和生成树
无向图的连通性
要想判定一个无向图是否为连通图,或有几个连通 分量,通过对无向图遍历即可得到结果。
for( v=0; v<G.vexnum; ++v ) if( !visited[v] ) DFS(G,v); //对尚未访问的顶点调用DFS
}
void DFS (Graph G, int v) { //从第v个顶点出发递归地深度优先遍历图G
visited[v]=TRUE ; Visit(v); //访问第v个顶点 //对v的尚未访问的邻接顶点w递归调用DFS for(w=FirstAdjVex(G,v); w>=0; w=NextAdjVex(G,v,w))
解决方案:附设访问标志数组visited[0..n-1],它的初 始状态为0,在图的遍历过程中,一旦某一个顶点i 被访问,就立即改 visited [i]为1,防止它被多次访问。
1.深度优先搜索(DFS, Depth_First Search )
基本思想:(1)从图中某顶点V0出发,访问此顶 点,然后依次从V0的各个未被访问的邻接点出发深 度优先搜索遍历图,直至图中所有和V0有路径相通 的顶点都被访问到;