C++ 数据结构-图相关操作的算法思路

目录

1.回路的判断:

2.普利姆-最小生成树

3.克鲁斯特卡尔-最小生成树

4.迪杰斯特拉-最短路径

5.图的最长路径(不走重复路)

6.有向无环图的关键路径


1.回路的判断:

用深度优先遍历,在有向图中如果遍历过程中重复访问到已经访问过的点,那么这个有向图就是就是有回路;如果是无向图,重复访问到了祖先结点那么这个无向图就存在回路。

2.普利姆-最小生成树

需要输入一个开始结点,新建一个对象数组arr [ size ] (nodeIndex,lowcost)  ,其中nodeIndex指的是结点在邻接矩阵或者邻接表的数组下标,其中arr[ i ] 表示  nodeIndex 到 i 的 是最短路径,消耗是lowcost。

对新加入的结点进行遍历边,比对 arr[i] ,如果新的边比arr[i]更小那么就重新覆盖 arr[i]的值,然后再旋转lowcost最小的点,再进行进行加入。反复执行次操作。

1.假设刚开始输入是A ,那么遍历 A 的边 ,初始化最小值 ,得到最小的边是(A,C),.然后把C 加入到集合

2 遍历新结点C的所有边,其中(C,B)要比原来的(A,B)要小 ;(C,E),(C,F)要比原先的(A,E)  (A,F)要小,覆盖值,不断重复步骤2,直到遍历n次(结点总数)

次数\结点 A B C D E F 已加入的点 最小结点 备注
1 (null) (A,6) (A,1) (A,5) (A,∞) (A,∞) (A) C 把C加入到集合
2 (null) (C,5) (null) (A,5) (C,6) (C,4) (A,C) F (C,B)比原来的(A,B)小,覆盖
3 (null) (C,5) (null) (F,2) (C,6) (null) (A,C,F) D (F,D)比(A,D)小
4 (null) (C,5) (null) (null) (C,6) (null) (A,C,F,D) B D的边没有原来的小
5 (null) (null) (null) (null) (B,3) (null) (A,C,F,D,B) E (B,E)比(C,E)小
6 (null) (null) (null) (null) (null) (null) (A,C,F,D,B,E) 结束 总共6个结点,共遍历6次

3.克鲁斯特卡尔-最小生成树

  刚开始,每个结点为各立为一组连通分量。连通分量之间选出最短的边,同通过最短的边,来合并连通分量,反复直到所有结点在同一个连通分量中,结束,或者无可以连接的边结束。当添加最短边时出现回路则选下一条边

对边进行从小到大排序:

(A,C,1)(D,F,2)(B,E,3)(C,F,4)(A,D,5)(B,C,5)(C,D,5)(A,B,6)(C,E,6)(E,F,6)

初始连通分量组 A B C D E F
第1小边(A,C) (A,C) B D E F
第2小边(D,F) (A,C) B (D,F) E
第3小边(B,E) (A,C) (B,E) (D,F)
第4小边(C,F) (A,C,D,F) (B,E)
第5小边(A,D),已在同一集合中,形成回路 (A,C,D,F) (B,E)
第6小边(B,C) (A,C,D,F,B,E)
全部结点在同一集合中,结束            

4.迪杰斯特拉-最短路径

    目标:输入一个起始结点,求起始结点到其他结点的最短路径和代价。需要提前初始化好邻接矩阵 adjacencyMatrix_。

假设输入起始点A,当前路径 A  (也是已访问的点),

对象数组的对象元素 时   (最小代价 lowcost_,和 最短路径  pathIndex_)

1.求到所有点的代价(A,C,10) (A,E,30) ,(A,F,100) ,选取最小代价的直接目标结点currentPathIndex(C)。加入到当前路径currentPath (A,C)  代价lowestCost为10.

2.即

currentPath= lowestPaths[currentPathIndex].pathIndex_  + currentPathIndex ;
lowestCost=lowestPaths[currentPathIndex].lowcost_

3.遍历LowestPaths[0....j...n]  (排除在CurrentPath的点)

if (lowestCost+ adjacencyMatrix_[currentPathIndex][j] <lowestPaths[j].lowcost_) {
    lowestPaths[j].lowcost_= lowestCost+ adjacencyMatrix_[currentPathIndex][j] ;
    lowestPaths[j].pathIndex_=currentPath;
}

  重复 2,3

求解步骤:


5.图的最长路径(不走重复路)

     不管是有向图或者无向图都适用的递归方法,建议使用邻接矩阵的数据结构,当图是有向无环图的时候,求的是关键路径。主要思想是:当已知源节点到目标结点的前继结点的最长路径时, 就可求得  源节点到目标结点的最长路径..

加入求 结点V0 到 Vn 的最长路径。那么首先要列出Vn的前驱结点集(Vxi,Vxi....) 

有递归函数fun(V0,Vn) 表示V0到Vn的最长路径 。其值  =Max(fun(V0,Vxi)+arc[Vxi][Vn]).通过次方法找到最长路径。找最短路径也可以参考此方法

函数格式      double fun( src , target , vector<int> & hasVisits)

提前初始化邻接矩阵 arc[][]。

0.如果源结点和目标结点相同则返回0。

1.已访问的结点集 hasVisits为引用形参,把目标结点target 加入进该集合。

2.寻找还未访问的目标结点的前继结点。

3.判断邻接矩阵arc[源结点][目标结点] 的是否是∞,如果为真初始化最大路径maxValue为最小浮点值,如果为假  maxValue为设置为arc[源结点][目标结点]。

4..拷贝hasVisits出一个副本,遍历前继结点集合,

value = fun(源结点,某个前继结点,hasVisits的副本引用) + arc[某个前继结点][目标结点]

,如果value大于maxvalue时,maxvalue赋值成value且 hasVisit赋值成hasVisits的副本引用。最后递归结束时hasVisits就是最大路径,返回值就是最大代价。

6.有向无环图的关键路径

主要思想就是 找出 最早开始时间和最晚结束时间相等的结点

起始结点的最早开始时间是 0 ,把代价当作时间。

每个结点最早开始时间 =   max(前继结点的最早开始时间+ arc[前继结点][当前结点])

终点结点的最晚结束时间=终点结点的最早开始时间。

每个结点最晚结束时间 =    min((后继结点的最晚结束时间   -  arc[当前结点][后继结点]) 

最早开始时间和最晚结束时间相等的结点就是关键结点,通路就是关键路径

猜你喜欢

转载自blog.csdn.net/superSmart_Dong/article/details/108805855