最小生成树

目录

带权图

带权图java代码实现

最小生成树

Kruskal算法

​切分定理

Kruskal算法的java代码实现

Prim算法

Prim算法的java代码实现

 总结


带权图

 边上的权是附加的额外信息,可以代表不同公路的收费等你需要的信息。

带权图java代码实现

port java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import java.util.Scanner;
import java.util.TreeSet;

//暂时支持无向带权图
public class WeightedGraph {
    private int V;
    private int E;
    //TreeMap传入的第二个元素是权值类型
    // 我们这里用的是Integer,具体用什么可以自行修改
    private TreeMap<Integer, Integer>[] adj;

    public WeightedGraph(String file){
        File file = new File(filename);
        try(Scanner scanner = new Scanner(file)){
            V = scanner.nextInt();//读取顶点信息
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new TreeMap[V];
            for(int i = 0; i < V; i++){
                adj[i] = new TreeMap<Integer, Integer>();
            }

            E = scanner.nextInt();//读取边的信息
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);//判断合法性
                int wight = scanner.nextInt();//读取权值
                //不要自环边
                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                //不要平行边
                if(adj[a].containsKey(b)) throw new IllegalArgumentException("");

                adj[a].put(b, weight);//传入weight
                adj[b].put(a, weight);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }
    public void validateVertex(int v) {
        if (v < 0 || v >= V) {
            throw new IllegalArgumentException("vertex" + "is invalid");
        }
    }
        public int V() {return V;}
        public int E() {return E;}

        public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].containsKey(w);
        }
        //返回和v相邻的所有顶点
    public Iterable<Integer> adj(int v){
        validateVertex(v);
        return adj[v].keySet();//返回TreeMap中所有的键
    }
    //返回权值
    public int getWeight(int v, int w){
        if(hasEdge(v, w))
        return adj[v].get(w);//获得w这个键对应的权值
        throw new IllegalArgumentException(String.format("no edge %d - %d", v, w));
    }

    public int degree(int v){
        validateVertex(v);
        return adj[v].size();
    }
    public void removeEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        adj[v].remove(w);
        adj[w].remove(v);
    }
    @Override
    public Object clone(){
        try{
            WeightedGraph cloned = (WeightedGraph) super.clone();
            cloned.adj = new TreeMap[V];
            for(int v = 0; v < V; v++){
                cloned.adj[v] = new TreeMap<Integer, Integer>();
                for(Map.Entry<Integer, Integer>entry : adj[v].entrySet())
                    cloned.adj[v].put(entry.getKey(), entry.getValue());
            }
            return cloned;
        }
        catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        return null;
    }
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("V = %d, E = %d\n"), V, E);
        for(int v = 0; v < V; v++){
            sb.append(String.format("%d : ", v));
            for(Map.Entry<Integer, Integer>entry : adj[v].entrySet())
                sb.append(String.format("(%d : %d)", entry.getKey(), entry.getValue()));
            sb.append('\n');
        }
        return sb.toString();
    }

      public static void main(String[]args){
        WeightedGraph g = new WeightedGraph("g.txt");
        System.out.println(g);
      }

}

最小生成树

Kruskal算法

同一张图的不同生成树的权值和大小不同,最小生成树就是求权值和最小的生成树。

在选最短的边的同时要注意不要和已选的边形成环。如下图,我们成功选了六条边连接了七个顶点,形成了最小生成树。

 切分定理

 Kruskal算法的java代码实现

import java.util.ArrayList;
import java.util.Collections;

public class Kruskal {

    private WeightedGraph G;
    private ArrayList<WeightedEdge> mst;

    public Kruskal(WeightedGraph G){

        this.G = G;
        mst = new ArrayList<>();

        CC cc = new CC(G);
        if(cc.count() > 1) return;

        ArrayList<WeightedEdge> edges = new ArrayList<>();
        for(int v = 0; v < G.V(); v ++)
            for(int w: G.adj(v))
                if(v < w)
                    edges.add(new WeightedEdge(v, w, G.getWeight(v, w)));

        Collections.sort(edges);

        UF uf = new UF(G.V());
        for(WeightedEdge edge: edges){
            int v = edge.getV();
            int w = edge.getW();
            if(!uf.isConnected(v, w)){
                mst.add(edge);
                uf.unionElements(v, w);
            }
        }
    }

    public ArrayList<WeightedEdge> result(){
        return mst;
    }

    public static void main(String[] args){

        WeightedGraph g = new WeightedGraph("g.txt");
        Kruskal kruskal = new Kruskal(g);
        System.out.println(kruskal.result());
    }
}

 

Prim算法

Prim算法的java代码实现

import java.util.ArrayList;
import java.util.Queue;
import java.util.PriorityQueue;

public class Prim {

    private WeightedGraph G;
    private ArrayList<WeightedEdge> mst;

    public Prim(WeightedGraph G){

        this.G = G;
        mst = new ArrayList<>();

        CC cc = new CC(G);
        if(cc.count() > 1) return;

        boolean visited[] = new boolean[G.V()];
        visited[0] = true;
        Queue pq = new PriorityQueue<WeightedEdge>();
        for(int w: G.adj(0))
            pq.add(new WeightedEdge(0, w, G.getWeight(0, w)));

        while(!pq.isEmpty()){

            WeightedEdge minEdge = (WeightedEdge) pq.remove();
            if(visited[minEdge.getV()] && visited[minEdge.getW()])
                continue;

            mst.add(minEdge);

            int newv = visited[minEdge.getV()] ? minEdge.getW() : minEdge.getV();
            visited[newv] = true;
            for(int w: G.adj(newv))
                if(!visited[w])
                    pq.add(new WeightedEdge(newv, w, G.getWeight(newv, w)));
        }
    }

    public ArrayList<WeightedEdge> result(){
        return mst;
    }

    public static void main(String[] args){

        WeightedGraph g = new WeightedGraph("g.txt");
        Prim prim = new Prim(g);
        System.out.println(prim.result());
    }
}

 总结

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值