06-数据结构之图,邻接表,“普里姆算法“找到最短路径

应用场景-修路问题

在这里插入图片描述

1.有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通

2. 各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里

3. 问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?

思路: 将10条边,连接即可,但是总的里程数不是最小.
正确的思路,就是尽可能的选择少的路线,并且每条路线最小,保证总里程数最少.

/**
 * 图的结构的实现主要是 领接矩阵 和邻接表, 矩阵存在浪费很多空间 , 不是特别好的, 所以我们使用邻接表 实现
 * 普里姆 算法, 找到一个最短路径联通整个村庄的路,
 * 
 */
public class Test1 {

    public static void main(String[] args) {

        /**
         *	上图为邻接矩阵的表达方式, 10000表示为空 A-B 的距轻松可以看到是 5
         *              a       b       c       d         e       f     g
         *
         * 	      a      10000   5       7       10000   10000   10000   2
         *        b     5        10000   10000   9       10000   10000   3
         *        c     7        10000   10000   10000   8       10000   10000
         *        d     10000    9       10000   10000   10000   4       10000
         *        e     10000    10000   8       10000   10000   5       4
         *        f     10000    10000   10000   4       5       10000   6
         *        g     2        3       10000   10000   4       6       10000
         */

        /**
         *	使用邻接表表达以上数据结构
         */
        Map<String, PointPower[]> map = new HashMap<String, PointPower[]>();
        map.put("A", new PointPower[]{
                new PointPower("B", 5),
                new PointPower("C", 7),
                new PointPower("G", 2),
        });
        map.put("B", new PointPower[]{
                new PointPower("A", 5),
                new PointPower("D", 9),
                new PointPower("G", 3),
        });
        map.put("C", new PointPower[]{
                new PointPower("A", 7),
                new PointPower("E", 8),
        });
        map.put("D", new PointPower[]{
                new PointPower("B", 9),
                new PointPower("F", 4),
        });
        map.put("E", new PointPower[]{
                new PointPower("C", 8),
                new PointPower("F", 5),
                new PointPower("G", 4),
        });
        map.put("F", new PointPower[]{
                new PointPower("D", 4),
                new PointPower("E", 5),
                new PointPower("G", 6),
        });
        map.put("G", new PointPower[]{
                new PointPower("A", 2),
                new PointPower("B", 3),
                new PointPower("E", 4),
                new PointPower("F", 6),
        });

        // 开始从那个点开始找
        List<String> startPointList = new ArrayList<>();
        startPointList.add("A");

        // 当前访问的元素
        String startPoint = null;

        // 访问过的元素
        Set<String> visited = new HashSet<>();

        // 这个循环就是表示输出多少条边
        for (int i = 0; i < map.size() -1; i++) {

            // 找到最小的元素索引
            int minIndex = Integer.MAX_VALUE;
            // 最小元素的权值
            int minPower = Integer.MAX_VALUE;
            // 最小元素所在点
            String minPoint = null;

            for (int x = 0; x < startPointList.size(); x++) {
                startPoint = startPointList.get(x);
                // 获得起始点的所有边
                PointPower[] pointPowers = map.get(startPoint);
                for (int j = 0; j < pointPowers.length; j++) {
                    PointPower thisPower = pointPowers[j];

                    if (thisPower.power < minPower && !visited.contains(thisPower.pint)  ) {
                        minIndex = j;
                        minPower = pointPowers[j].power;
                        minPoint = startPoint;
                    }
                }
            }


            PointPower[] pointPowers = map.get(minPoint);

            System.out.println("边=" + minPoint + " --> " + pointPowers[minIndex].pint + ",权值:" + pointPowers[minIndex].power);
            visited.add(minPoint);
            visited.add(pointPowers[minIndex].pint);
            startPointList.add(pointPowers[minIndex].pint);

        }


    }
}

/**
 * 这是一个点和权值得类
 */
class PointPower {
    // 表示这个点的名称
    String pint;
    // 表示这个点距离下一个点的权
    int power;

    public PointPower(String pint, int power) {
        this.pint = pint;
        this.power = power;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值