欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

最小生成树(Minimum Cost Spanning Tree)

程序员文章站 2022-06-20 09:02:47
...

MST的性质
若(u, v)是一条具有最小权值的边,则存在一棵包含边(u, v)的最小生成树
最小生成树的算法就是基于MST这个性质写的
一、Prim算法
Prim算法也称为"加点法",从v0开始,根据MST的性质每次添加一条最小花费的顶点到集合U
Prim特有属性

class Closedge {    // closedge[]的作用是记录从U到V的最小花费和邻接边
    String adjvex;	// U集合到V-U集合的邻接顶点
    int lowcost;	// U集合到V-U集合的邻接边的权值
}
Closedge[] closedge;
closedge = new Closedge[VEXNUM];

Prim

public void Prim(String v0) {
    // 初始化closedge
    int x0 = Locate(v0);
    for (int i = 0; i < VEXNUM; i++) {
        closedge[i] = new Closedge(null, INF);
    }
    for (int i = 0; i < VEXNUM; i++) {
        if (i != x0){
            closedge[i].adjvex = v0;
            if (arcs[x0][i] < INF){
                closedge[i].lowcost = arcs[x0][i];
            }
        }
    }
    closedge[x0].lowcost = 0;

    // 利用MST的性质,每次添加最小花费的节点进入集合
    for (int w = 1; w < VEXNUM; w++) {
        // 找到closedge中的最小花费及其对应顶点
        int min = INF;
        int k = -1;
        for (int i = 0; i < VEXNUM; i++) {
            if (closedge[i].lowcost!=0 && min>closedge[i].lowcost){
                min = closedge[i].lowcost;
                k = i;
            }
        }

        // 根据顶点更新closedge信息
        closedge[k].lowcost = 0;
        for (int i = 0; i < VEXNUM; i++) {
            if (arcs[k][i] < closedge[i].lowcost){
                closedge[i].lowcost = arcs[k][i];
                closedge[i].adjvex = vexs[k];
            }
        }
    }
}

二、Kruskal算法
kruskal的特有属性

class Edge implements Comparable{	// edge[]用来记录各边,Edge类实现了Comparable用来根据边的权值排序edge[]
    int head, tail;
    int lowcost;
    
    @Override
    public int compareTo(Object o) {
        return this.lowcost - ((Edge) o).lowcost;
    }
}
public static ArrayList<Edge> edges;    // 记录各条边的信息
edges = new ArrayList<>();
public static Integer[] vexset; // 记录各个顶点所属连通分量
vexset = new Integer[VEXNUM];

Kruskal过程

public void Kruskal() {
    // 初始化边集合
    for (int i = 0; i < VEXNUM; i++) {
        for (int j = i+1; j < VEXNUM; j++) {
            if (arcs[i][j]!=INF)
                edges.add(new Edge(i, j, arcs[i][j]));
        }
    }

    // 初始化vexset
    for (int i = 0; i < VEXNUM; i++) {
        vexset[i] = new Integer(i);
    }

    Collections.sort(edges);     // 对边集合进行排序

    // 添加边到集合中
    for (int i = 0; i < ARCNUM; i++) {
        int vs0 = vexset[edges.get(i).head];
        int vs1 = vexset[edges.get(i).tail];

        if (vs0 != vs1){    // 更新vs1节点所在连通分量
            System.out.println(edges.get(i));   // 访问该边
            for (int j = 0; j < VEXNUM; j++) {
                if (vs1 == vexset[j]){
                    vexset[j] = vs0;
                }
            }
        }
    }
}
相关标签: Graph