最小生成树之prim算法(邻接表和邻接矩阵)

抽象类

import java.util.List;

public abstract class Adjacency<V> {

    /** 总权重 */
    protected int totalWeight;

    /** 顶点的父亲 */
    protected int[] parent;

    /** 保存顶点的添加顺序 */
    protected List<Integer> list;

    /**
     * prim
     * @param startingVertex 开始的顶点
     */
    public abstract void prim(int startingVertex);

    /**
     * 打印结果
     */
    public abstract void print();
}

邻接表

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class AdjacencyList<V> extends Adjacency<V> {

    public class Edge {

        /** 起始顶点 */
        public int start;

        /** 结束顶点 */
        public int end;

        /** 权重 */
        public int weight;

        public Edge(int start, int end, int weight) {
            this.start = start;
            this.end = end;
            this.weight = weight;
        }
    }

    /** 存储顶点 */
    public List<V> vertices = new ArrayList<>();

    /** 邻接表 */
    public List<List<Edge>> neighbors = new ArrayList<>();

    public AdjacencyList(V[] vertices, int[][] edges) {
        createWeightedGraph(Arrays.asList(vertices), edges);
    }

    /**
     * 构建邻接线性表
     */
    private void createWeightedGraph(List<V> vertices, int[][] edges) {
        this.vertices = vertices;
        for(int i = 0; i < vertices.size(); i++) {
            neighbors.add(new ArrayList<>());
        }
        for(int i = 0; i < edges.length; i++) {
            neighbors.get(edges[i][0])
                    .add(new Edge(edges[i][0], edges[i][1], edges[i][2]));
        }
    }

    @Override
    public void prim(int startingVertex) {
        //权重
        double[] cost = new double[vertices.size()];
        for(int i = 0; i < cost.length; i++) {
            //初始化
            cost[i] = Double.POSITIVE_INFINITY;
        }
        //初始化是0
        cost[startingVertex] = 0;
        //父节点
        this.parent = new int[vertices.size()];
        parent[startingVertex] = -1;
        //树的总权值
        this.totalWeight = 0;
        //保存符合条件的顶点。
        this.list = new ArrayList<>();

        //找出最小权重
        while(list.size() < vertices.size()) {
            //当前顶点
            int u = -1;
            double currentMinCost = Double.POSITIVE_INFINITY;
            for(int i = 0; i < vertices.size(); i++) {
                if(!list.contains(i) && cost[i] < currentMinCost) {
                    currentMinCost = cost[i];
                    u = i;
                }
            }
            //增添新的顶点
            list.add(u);
            //把当前权值增加给数的总权值
            totalWeight += cost[u];

            //在待查找的顶点调整顶点相邻边的cost数组
            for(Edge e : neighbors.get(u)) {
                if(!list.contains(e.end) && cost[e.end] > e.weight) {
                    cost[e.end] = e.weight;
                    parent[e.end] = u;
                }
            }
        }
    }

    @Override
    public void print() {
        System.out.println("total weight is: " + super.totalWeight);
        System.out.print("查找顺序为:");
        for(int i : super.list) {
            System.out.print(" " + vertices.get(i));
        }
        System.out.println("\n节点之间的关系为: ");
        int[] parent = super.parent;
        for(int i = 0; i < parent.length; i++) {
            if(parent[i] != -1) {
                System.out.println(vertices.get(i) + "---" + vertices.get(parent[i]));
            }
        }
    }

}

邻接矩阵

import java.util.ArrayList;

public class AdjacencyMatrix<V> extends Adjacency<V> {

    private String[] vertices;

    private int[][] matrix;

    public AdjacencyMatrix(String[] vertices, int[][] matrix) {
        this.vertices = vertices;
        this.matrix = matrix;
    }

    @Override
    public void prim(int startingVertex) {
        //权重
        double[] cost = new double[vertices.length];
        for(int i = 0; i < cost.length; i++) {
            //初始化
            cost[i] = Double.POSITIVE_INFINITY;
        }
        //初始化是0
        cost[startingVertex] = 0;
        //父节点
        this.parent = new int[vertices.length];
        parent[startingVertex] = -1;
        //树的总权值
        this.totalWeight = 0;
        //保存符合条件的顶点。
        this.list = new ArrayList<>();

        //找出最小权重
        while(list.size() < vertices.length) {
            //当前顶点
            int u = -1;
            double currentMinCost = Double.POSITIVE_INFINITY;
            for(int i = 0; i < vertices.length; i++) {
                if(!list.contains(i) && cost[i] < currentMinCost) {
                    currentMinCost = cost[i];
                    u = i;
                }
            }
            //增添新的顶点
            list.add(u);
            //把当前权值增加给数的总权值
            totalWeight += cost[u];

            //在待查找的顶点调整顶点相邻边的cost数组
            for(int e = 0; e < matrix[u].length; e++) {
                if(!list.contains(e) && cost[e] > matrix[u][e]) {
                    cost[e] = matrix[u][e];
                    parent[e] = u;
                }
            }
        }
    }

    @Override
    public void print() {
        System.out.println("total weight is: " + super.totalWeight);
        System.out.print("查找顺序为:");
        for(int i : super.list) {
            System.out.print(" " + vertices[i]);
        }
        System.out.println("\n节点之间的关系为: ");
        int[] parent = super.parent;
        for(int i = 0; i < parent.length; i++) {
            if(parent[i] != -1) {
                System.out.println(vertices[i] + "---" + vertices[parent[i]]);
            }
        }
    }
}

测试代码

public class TestPrim {

    public static void main(String[] args) {
    //测试用例随意写的
        String[] vertices = {"北京", "上海", "广州", "杭州", "长沙", "武汉", "南京"};

        System.out.println("----------邻接表----------");
        int[][] edges = {
            {0, 1, 7807}, {0, 3, 1331}, {0, 5, 2097},
            {1, 0, 7807}, {1, 2, 381}, {1, 3, 1267},
            {2, 1, 381}, {2, 3, 1015}, {2, 4, 1663},
            {3, 0, 1331}, {3, 1, 1267}, {3, 2, 1015}, {3, 4, 599}, {3, 5, 1003},
            {4, 2, 1663}, {4, 3, 599}, {4, 5, 533},
            {5, 0, 2097}, {5, 3, 1003}, {5, 4, 533}, {5, 6, 983},
            {6, 5, 983}
        };

        Adjacency<String> adjacencyList = new AdjacencyList<>(vertices, edges);
        adjacencyList.prim(0);
        adjacencyList.print();

        System.out.println("----------邻接矩阵----------");
        int[][] matrix = {
                {0, 7807, 0, 1331, 0, 2097, 0},      //北京
                {7870, 0, 381, 1267, 0, 0, 0},       //上海
                {0, 381, 0, 1015, 1663, 0, 0},       //广州
                {1331, 1267, 1015, 0, 599, 1003, 0}, //杭州
                {0, 0, 1663, 599, 0, 533, 0},        //长沙
                {2097, 0, 0, 1003, 533, 0, 983},     //武汉
                {0, 0, 0, 0, 0, 983, 0}              //南京
        };
        Adjacency<String> adjacencyMatrix = new AdjacencyMatrix<>(vertices, matrix);
        adjacencyMatrix.prim(0);
        adjacencyList.print();
    }
}

输出结果

----------邻接表----------
total weight is: 4842
查找顺序为: 北京 杭州 长沙 武汉 南京 广州 上海
节点之间的关系为: 
上海---广州
广州---杭州
杭州---北京
长沙---杭州
武汉---长沙
南京---武汉
----------邻接矩阵----------
total weight is: 4842
查找顺序为: 北京 杭州 长沙 武汉 南京 广州 上海
节点之间的关系为: 
上海---广州
广州---杭州
杭州---北京
长沙---杭州
武汉---长沙
南京---武汉
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值