最小生成树的两种方法

法一

代码

package kruskal;

import java.util.Arrays;

/**
 * 解决最小生成树的另一种方法
 */
public class KruskalDemo {
    public static void main(String[] args) {
        char[] datas = new char[]{'A','B','C','D','E','F','G'};
        int verxs = datas.length;
        int max = Integer.MAX_VALUE;
        int[][] weight = {
                {0,12,max,max,max,16,14},
                {12,0,10,max,max,7,max},
                {max,10,0,3,5,6,max},
                {max,max,3,0,4,max,max},
                {max,max,5,4,0,2,8},
                {16,7,6,max,2,0,9},
                {14,max,max,max,8,9,0}
        };
        Graph graphs = new Graph(verxs,datas,weight);
        //输出公交站
        graphs.show();
//        System.out.println("公交站的路线条数有" + graphs.weightLen);
       /* System.out.println("所有边为" + Arrays.toString(graphs.edges));
        graphs.edgeSort();*/
//        System.out.println("排序后的边为" + Arrays.toString(graphs.edges));
        graphs.minTree();
        System.out.println("最小生成树为" + Arrays.toString(graphs.overEdges));
    }
}

/**
 * 生成公交站的方法
 */
class Graph{
    int verxs;//顶点的个数
    char[] datas;//顶点的代号
    int[][] weight;//边的值
    int weightLen;//边的条数
    Edges[] edges;//边的集合数组
    int[] ends;//用于存储顶点的尾节点
    Edges[] overEdges;//用来存储已经成功加入的边(即最小树的边)
    //构造方法
    public Graph(int verxs, char[] datas, int[][] weight) {
        this.verxs = verxs;
        this.ends = new int[verxs];
        this.datas = datas;
        this.weight = weight;
        for (int i = 0; i < verxs; i++) {//用以统计边的数量
            for (int j = i + 1; j < verxs; j++) {
                if (weight[i][j] != Integer.MAX_VALUE){
                    weightLen++;//边条数自增
                }
            }
        }
        this.edges = new Edges[weightLen];
        alledges();//将所有的边加入到边的集合中
        this.overEdges = new Edges[verxs - 1];//初始化一个储存结果的数组
    }
    public int findChar(char value){
        int temp = -1;
        for (int i = 0; i < datas.length; i++) {
            if (datas[i] == value){
                temp = i;
                return temp;
            }
        }
        return temp;
    }
    //生成最小生成树
    public void minTree(){
        //将边集合进行排序
        edgeSort();
        for (int i = 0; i < edges.length; i++) {
            //获得顶点的尾结点
            int p1 = findChar(edges[i].start);
            int p2 = findChar(edges[i].end);
            //获得尾结点
            int m = getEnd(ends,p1);
            int n = getEnd(ends,p2);
            if (m != n){//不连通的情况
                ends[m] = n;
                addEdges(edges[i]);
//                System.out.println(edges[i]);
            }

        }
    }
    //寻找一个节点的尾节点,获取下标为i的顶点的终点
    public int getEnd(int[] ends,int i){
        while (ends[i] != 0){
            i = ends[i];
        }
        return i;
    }
    //将判断结束的边(符合条件的边)加入到overEdges中
    public void addEdges(Edges e){
        for (int i = 0; i < overEdges.length; i++) {
            if (overEdges[i] == null){
                overEdges[i] = e;
                break;
            }
        }
    }
    //写一个边的集合
    public void alledges(){
        for (int i = 0; i < verxs; i++) {//用以添加边
            for (int j = i + 1; j < verxs; j++) {
                if (weight[i][j] != Integer.MAX_VALUE){
                    for (int k = 0; k < edges.length; k++) {
                        if (edges[k] == null){
                            edges[k] = new Edges(datas[i],datas[j],weight[i][j]);
                            break;
                        }
                    }
                }
            }
        }
    }
    //对边进行排序
    public void edgeSort(){
        for (int i = 0; i < edges.length; i++) {
            for (int j = 0; j < edges.length - 1 - i; j++) {
                if (edges[j].value > edges[j + 1].value){
                    int temp = edges[j].value;
                    edges[j].value = edges[j + 1].value;
                    edges[j + 1].value = temp;
                }
            }
        }

    }

    /**
     * 将数据展示出来
     */
    public void show(){
        System.out.println("公交站的值为");
        for (int i = 0; i < verxs; i++) {
            for (int j = 0; j < verxs; j++) {
                System.out.printf("%-12d\t",weight[i][j]);
            }
            System.out.println();
        }
    }
}
class Edges{
    char start;//边的起始顶点
    char end;//边的终点
    int value;//边对应的值

    public Edges(char start, char end, int value) {
        this.start = start;
        this.end = end;
        this.value = value;
    }

    @Override
    public String toString() {
        return "edges{" +
                "<" + start +
                ",>" + end +
                "-->" + value +
                '}';
    }
}

法二

代码

package prim;

import java.util.Arrays;

/**
 * 最小生成树的生成
 */
public class PrimDemo {
    public static void main(String[] args) {
        char[] datas = new char[]{'A','B','C','D','E','F','G'};
        int verxs = datas.length;
        int max = 10000;
        int[][] weight = {
                {max,5,7,max,max,max,2},
                {5,max,max,9,max,max,3},
                {7,max,max,max,8,max,max},
                {max,9,max,max,max,4,max},
                {max,max,8,max,max,5,4},
                {max,max,max,4,5,max,6},
                {2,3,max,max,4,6,max}
        };
        Graph graph = new Graph(verxs,datas,weight);
        graph.show();
        graph.minTree(1);
    }
}

/**
 * 生成村庄的类
 */
class Graph{
     public int verxs;//顶点的个数
     public char[] datas;//顶点的代号
     public int[][] weight;//边的值
    public Graph(int verxs, char[] datas, int[][] weight) {
        this.verxs = verxs;
        this.datas = datas;
        this.weight = weight;
    }
    public void show(){
        System.out.println("村庄的值为");
        for (int[] data:weight) {
            System.out.println(Arrays.toString(data));
        }
    }


    /**
     *   //生成最小生成树的方法
     * @param v  表示开始遍历的节点的位置
     */
    public void minTree(int v){
        //使用一个boolean数组表示对应的节点是否被添加,false表示没有被添加
        boolean[] visited = new boolean[this.verxs];
        //将起始节点加入
        visited[v] = true;
        //行列的命名
        int row = 0;
        int line = 0;
        for (int i = 0; i < verxs - 1; i++) {
            int minData = 10000;
            for (int j = 0; j < verxs; j++) {//表示的是已经被添加过的
                for (int k = 0; k < verxs; k++) {//表示还没有被添加过的
                    if (visited[j] && !visited[k] && minData > weight[j][k]){
                        row = j;
                        line = k;
                        minData = weight[j][k];
                    }
                }
            }
//            System.out.println(line);
            System.out.println("节点" + datas[row] + "到节点" +
                    datas[line] + "的值为" + minData);
            visited[line] = true;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值