7.3图的遍历

遍历需要对图中所有顶点进行访问,并且每个顶点只能访问一次,但因为任何顶点都可能邻接,所以会遇到遍历了一轮又回到原来的结点上,这时需要设立标记,记录结点是否已经被访问。遍历算法有两种:深度优先搜索广度优先搜索

7.3.1深度优先搜索DFS

步骤:

  • 选取一个顶点访问
  • 从该顶点的邻接点中选取一个访问
  • 从该邻接点的邻接点中选取一个访问
  • 如果一个点的邻接点都被访问,则退回上一个点
  • 直到与第一个顶点连通的所有顶点都被访问
  • 如果还有未访问的点(说明不连通),则选取该点访问,并重复上述操作,直到所有点都被访问

深度优先搜索算法



int



7.3.2广度优先搜索BFS

步骤:

  • 选择一个顶点访问
  • 依次访问该顶点所有仍未访问的邻接点
  • 按照上面的次序,访问邻接点的所有未被访问的邻接点
  • 重复上面的过程直到已访问顶点的邻接点都被访问
  • 如果图中有未被访问的点(不连通),则选取该点访问并重复上面的操作

实质:从一个顶点开始,依次访问与该顶点相连且路径长度为1,2,3,...的顶点,类似于树的层序遍历。

广度优先搜索算法--队列

  • 设置访问数组并初始化为0
  • 创建空队列
  • 选取一个顶点,访问数组单元置为1,进队
  • 队头出队并记录为u
  • 依次置u的邻接点访问数组单元为1,并让其进队
  • 重复第四第五步直到队列为空
  • 如果还有未被访问的,外层循环找到它然后从第三步开始重复操作
int



7.4图的连通性问题

7.4.1无向图的连通分量和生成树

  • 对于连通图,从一个顶点出发可以访问所有顶点
  • 对于非连通图,需要从多个顶点搜索,从每个顶点出发得到的是一个连通分量的顶点集,加上与之关联的边就可以构成连通分量

对于连通图而言,遍历过程经过的边数仅有



条,这些边与图中顶点合起来就构成该图的极小连通子图,也就是


生成树。根据遍历方法的不同,生成树分为

深度优先生成树

广度优先生成树。对于非连通图而言,从每个连通分量的顶点出发可以得到彼此不相交的

多棵生成树,这些生成树合起来称为

生成森林


7.4.2有向图的强连通分量

深度优先搜索求有向图的强连通分量--正反都来一次

  • 从一个顶点出发,沿着顶点为尾的弧进行深度优先搜索,按照完成搜索的排列顶点(完成搜索即该顶点的所有邻接点都被访问)
  • 从最后一个完成搜索的顶点出发,沿着顶点为头的弧进行逆向深度优先搜索
  • 如果逆向搜索一次不能访问所有点,则从剩余的点中选择正向最后完成搜索的点,进行逆向深度优先搜索
  • 每次逆向搜索得到的是一个强连通分量的顶点集




java 查找 图像 轮廓 java大图查找小图_最小生成树算法matlab


上图的说明

  • 正向:访问1--访问2--2的邻接点为空(即未访问邻接点为空)所以首先完成搜索--退回1--访问3--访问4--4的未访问邻接点为空所以完成搜索--退回3--3完成搜索--退回1--1完成搜索
  • 逆向:从最后完成的搜索的1出发,沿着顶点为头的弧--访问3--访问4--结束第一次逆向访问--余下顶点为2--访问--结束

7.4.3最小生成树

现在图的边带有权重,希望得到的生成树所有边的权重之和最小。

性质:将顶点集拆为两部分,对于分居两部分的两个顶点构成的边,其中权重最小必然有一棵最小生成树包含它.

(一)普里姆Prim算法

思路:从一个顶点开始,找与之相关联的权重最小的边及对应的顶点加入,然后把这两个顶点看做整体,找它们与“外部”相关联的边中权重最小的,将点和边加入,重复上述操作直到选完所有顶点。

抽象化:从


开始,在所有


的边


中选取权重最小的


加入


,并且


加入


,直到



算法实现:

  • 定义辅助数组closedge,每个单元存放权重最小的边对应的顶点编号以及权重
  • 求出发顶点u的编号
  • 对剩余顶点的closedge单元初始化,顶点信息为u,权值为邻接矩阵中对应的
  • 出发顶点的closedge单元的权值为0
  • 选择其余顶点中权值最小的,将其并入U集(权值改为0),并得到生成树的边
  • 对剩余顶点的权值进行更新,即如果与新顶点的边权更小,就改为这个权
void


双重循环做了平方次,所以时间复杂度为



java 查找 图像 轮廓 java大图查找小图_优先队列prim算法java_02


(二)克鲁斯卡尔算法

思路:不断加入权重最小且位于不同连通分量上的边

抽象化:初始状态只有顶点无边


,选择剩余边中权重最小的,如果该边依附的顶点在


中处于不同连通分量,则


中加入该边,否则舍弃该边,选择下一条权重最小的边


更直观:选择剩余边中权重最小的,如果和现有边构成环,则舍弃换下一条权重最小的...

:两种算法有何区别?

:普里姆算法是找顶点,克鲁斯卡尔算法是找边。如果边稠密就用普里姆算法,如果边稀疏就用克鲁斯卡尔算法