最小生成树

带权图

最小生成树_第1张图片

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

带权图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[] 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();
            }

            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 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();
                for(Map.Entryentry : 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.Entryentry : 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算法

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

最小生成树_第2张图片

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

最小生成树_第3张图片 切分定理

最小生成树_第4张图片

最小生成树_第5张图片

 Kruskal算法的java代码实现

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

public class Kruskal {

    private WeightedGraph G;
    private ArrayList mst;

    public Kruskal(WeightedGraph G){

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

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

        ArrayList 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 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算法

最小生成树_第6张图片

Prim算法的java代码实现

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

public class Prim {

    private WeightedGraph G;
    private ArrayList 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();
        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 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());
    }
}

 总结

最小生成树_第7张图片

你可能感兴趣的:(#数据结构与算法,java,开发语言,算法,数据结构)