生成树
生成树是对图遍历访问的一条无回路的遍历路径称为图的生成树,生成树不是唯一的,深度优先和广度优先的访问路径就是一棵生成树.深度优先搜索与广度优先搜索的生成树分别称为***,
最小生成树
最小生成树是对带有权值的图,生成树路径中权值总和最小的路径,称为最小生成树.求最小生成树的算法有 prim(普里姆)算法 和 kruskal(克鲁斯卡尔)算法:
prim算法:
假设图G=(V,E)是有n个顶点的连通图. T=(U,TE)是G的最小生成树,初值为空.首先从V中任选一个顶点放入U.(标记1:)然后从E中取一条边放入TE,这条边要满足:其中一个顶点在U中,一个在U之外(没在U中)。(这样的边不止一条)。这条边是权值最小的那条.然后把不在U的顶点放入U(这条边的另一端)。jump 标记1. 直到V中所有点都在U中, 这时TE中有n-1条边.最小生成树算法结束.算法时间复杂度是O(n2)
代码示例:
package stuct; import java.util.LinkedList; import java.util.List; public class Graph2 { int m = Integer.MAX_VALUE; public static void main(String[] args) { Graph2 main = new Graph2(); main.prim(main.matrix(),0); //打印结果 // 边 (0, 2)value=2 // 边 (2, 1)value=1 // 边 (2, 4)value=3 // 边 (4, 3)value=2 } /** * * @Title: matrix * @Description: TODO 图的邻接矩阵表示 * @param 设定文件 * @return void 返回类型 * @throws */ public Graph matrix() { //顶点集合 int[] nodes = {0,1,2,3,4}; //无向图的临接矩阵存储,对称矩阵,这个矩阵描述了图的边集合 //边表, 不带权,i表示行标, j表示列标.第i行表示第i个定点(i对应nodes顶点的key值和下标), //第i个顶点指向的顶点key 作为j的下标, 赋值1,表示有连接 //对于带权边的表示:用权值替换1,用MAX_VALUE替换0,主对角线置0, 表示指向自己, 不了,没啥用,还是置max算了 int[][] table = { {m, 4, 2, m, m},//第0号定点指向了第1号顶点和第3号顶点 {4, m, 1, 3, 4}, {2, 1, m, 6, 3}, {m, 3, 6, m, 2}, {m, 4, 3, 2, m}, }; //图的包装类 Graph g = new Graph(nodes,table); return g; } public void prim(Graph g,int begin) { // Graph g1 = (Graph) g.clone(); int len = g.nodes.length; //顶点数组, 记录g的顶点, 初始顶点是 begin int [] v = new int[len]; //指示v的下标 int l = 0; //初始化 for(int i = 0; i < v.length; i++) { v[i] = -1; } //边集合,记录v中顶点指向其他顶点的边 List<side> e = new LinkedList<side>(); v[l++] = begin; while(l<len) { //清除指向v中元素的边数据, 避免重复添加 for(int i = 0; i < len; i++) { //删除第b[l-1]列 g.table[i][v[l-1]] = m; } //把v[l-1]指向v以外的顶点的边加入边集合 for(int i = 0; i < len; i++) { if(g.table[v[l-1]][i] != m) { //有连接, 把边加入集合 e.add(new side(v[l-1],i,g.table[v[l-1]][i])); } } //找到最小边 side s = getMinSide(e); //将此边的v之外的顶点加入v v[l++] = s.u; //在边集合中删除 s e.remove(s); // System.out.println(s); } } private side getMinSide(List<side> e) { side s = null; for(side sd : e) { if(s == null) { s = sd; continue; } if(sd.value < s.value) { s = sd; } } return s; } } class side{ public int v; public int u; public int value;//权值 public side() { } public side(int v, int u, int value) { super(); this.v = v; this.u = u; this.value = value; } @Override public String toString() { return "边 ("+ v + ", " + u + ")"+ "value=" + value; } } class Graph{ public int[] nodes;//顶点的名称.比如第key号顶点,不可重复 public int[][] table;//权值 public Graph(int[] nodes, int[][] table) { this.nodes = nodes; this.table = table; } }
kruskal算法
来源:https://www.cnblogs.com/zhang01010/p/8691200.html