生成树
生成树是对图遍历访问的一条无回路的遍历路径称为图的生成树,生成树不是唯一的,深度优先和广度优先的访问路径就是一棵生成树.深度优先搜索与广度优先搜索的生成树分别称为***,
最小生成树
最小生成树是对带有权值的图,生成树路径中权值总和最小的路径,称为最小生成树.求最小生成树的算法有 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算法
来源:oschina
链接:https://my.oschina.net/u/4324343/blog/4023803