为了账号安全,请及时绑定邮箱和手机立即绑定

java面试---图的最小路径

标签:
Java
无权重

在查找最小路径上,图的题目特别多,无权重的情况,找最小路径就是图的广度优先遍历。广度优先遍历就是依靠队列来实现。由于比较简单,这里不贴代码了。

为什么是广度优先

图的遍历有深度和广度两种,那么为什么使用广度去找出最小路径呢。其实他成立的条件是无权重,就是每条路径的消费都是一样的。广度优先遍历对应的树的层次遍历,这样就更好理解了,树的层次遍历,由于是一层一层的看,那么层数最小的情况就是最短的情况。

无负权重

无负权重的情况下,迪杰斯特拉是个不错的选择。 迪杰斯特拉是大学算法课上基本都讲的内容。其实算法思想还好,写起来稍微繁琐一些。

算法讲解

迪杰斯特拉的重点就是对一个图标的填充。

节点 花费 是否访问
迪杰斯特拉

接下来我们来具体结合一个例子来说明这个表格如何填充
图片描述

如上图,起点为a,终点是f。

初始化表格

我们先初始化表格,因为a是起点,所以没有包含在内计算。这个计算其实就是把起点相关的初始化到表格里。b是可达的,其余节点都是不可达的,所以花费默认都是没有。

节点 花费 是否访问
b 2 -
c - -
d - -
e - -
f - -

查找最小消耗的节点

根据上图,最小消耗的就是b

继续访问节点

b就当做被访问过了,b到c是4,所以c的花费就是6,然后类推其他f,d,e

节点 花费 是否访问
b 2
c 6 -
d 3 -
e - -
f 7 -

重复的步骤

  1. 找出最小没有访问的节点
  2. 访问节点的邻居节点
  3. 更新图表,保存消耗最小的值

结果

节点 花费 是否访问
b 2
c 6
d 3
e 6
f 7

终点是f,结果就是7

画出路径

上面的情况只是找出了最小消耗,想找出路径,修改表格就好,保存对应的父节点

节点 父节点 花费 是否访问

代码实现


public class Dijkstra {

    public static void main(String[] args) {
        String[] startEnd = new String[2];
        Map<String, Node> initData = initData(startEnd);
        Set<String> process = new HashSet<>();
        Map<String, NodeCost> costList = new HashMap<>();

        init(initData, costList, startEnd[0]);
        find(initData, process, costList);

        NodeCost nodeCost = costList.get(startEnd[1]);
        LinkedList<String> list = new LinkedList<>();
        System.out.println(nodeCost.cost);
        list.addFirst(nodeCost.current);
        while (nodeCost != null) {

            list.addFirst(nodeCost.parent);
            nodeCost = costList.get(nodeCost.parent);
        }
        System.out.println(list);

    }

    public static void find(Map<String, Node> initData, Set<String> process, Map<String, NodeCost> costList) {
        NodeCost minNode = getMinNode(process, costList);
        while (minNode != null) {
            Node node = initData.get(minNode.current);
            Map<String, Integer> nextNode = node.nextNode;
            Iterator<Entry<String, Integer>> iterator = nextNode.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, Integer> next = iterator.next();
                int cost = minNode.cost + next.getValue();
                NodeCost nodeCost = costList.get(next.getKey());
                int oldCost = nodeCost.cost;
                if (oldCost > cost) {
                    nodeCost.parent = node.name;
                    nodeCost.cost = cost;
                }
            }
            process.add(node.name);
            minNode = getMinNode(process, costList);

        }

    }

    //找出最小消耗没有访问过的节点
    public static NodeCost getMinNode(Set<String> process, Map<String, NodeCost> costList) {

        Collection<NodeCost> values = costList.values();
        NodeCost preCost = null;

        for (NodeCost cost : values) {
            if (!process.contains(cost.current)) {
                if (preCost == null) {
                    preCost = cost;
                } else if (preCost.cost >= cost.cost) {
                    preCost = cost;
                }
            }

        }

        return preCost;
    }

    //初始化图表耗费
    public static void init(Map<String, Node> initData, Map<String, NodeCost> costList, String start) {
        Collection<Node> values = initData.values();
        Iterator<Node> iteratorValues = values.iterator();
        while (iteratorValues.hasNext()) {

            Node node = iteratorValues.next();
            Map<String, Integer> nextNode = node.nextNode;
            Iterator<Entry<String, Integer>> iterator = nextNode.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, Integer> next = iterator.next();
                NodeCost cost = new NodeCost();
                cost.parent = node.name;
                cost.current = next.getKey();
                if (node.name.equals(start)) {
                    cost.cost = next.getValue();
                } else {
                    cost.cost = Integer.MAX_VALUE;
                }
                NodeCost oldCost = costList.get(next.getKey());
                if (oldCost == null || oldCost.cost == Integer.MAX_VALUE) {
                    costList.put(next.getKey(), cost);
                }

            }
        }

    }

    //初始化图结构
    public static Map<String, Node> initData(String[] startEnd) {
        Map<String, Node> node = new HashMap<>();

        Node a = new Node();
        a.name = "a";
        a.nextNode = new HashMap<String, Integer>() {
            {
                put("b", 5);
                put("f", 2);
            }

        };

        node.put("a", a);

        Node b = new Node();
        b.name = "b";
        b.nextNode = new HashMap<String, Integer>() {
            {
                put("c", 4);
                put("e", 2);
            }

        };
        node.put("b", b);

        Node c = new Node();
        c.name = "c";
        c.nextNode = new HashMap<String, Integer>() {
            {
                put("d", 3);
                put("e", 6);
            }

        };
        node.put("c", c);

        Node d = new Node();
        d.name = "d";

        node.put("d", d);

        Node e = new Node();
        e.name = "e";
        e.nextNode = new HashMap<String, Integer>() {
            {

                put("d", 1);
            }

        };
        node.put("e", e);

        Node f = new Node();
        f.name = "f";
        f.nextNode = new HashMap<String, Integer>() {
            {

                put("b", 8);
                put("e", 7);
            }

        };
        node.put("f", f);

        startEnd[0] = "a";
        startEnd[1] = "d";

        return node;
    }

}

//图表的结构
class NodeCost {
    String current;
    String parent;
    Integer cost;

    public String getCurrent() {
        return current;
    }

    public void setCurrent(String current) {
        this.current = current;
    }

    public String getParent() {
        return parent;
    }

    public void setParent(String parent) {
        this.parent = parent;
    }

    public int getCost() {
        return cost;
    }

    public void setCost(int cost) {
        this.cost = cost;
    }

    @Override
    public String toString() {
        return "NodeCost [current=" + current + ", parent=" + parent + ", cost=" + cost + "]";
    }

}

//原始数据结构
class Node {
    String name;
    Map<String, Integer> nextNode = new HashMap<>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, Integer> getNextNode() {
        return nextNode;
    }

    public void setNextNode(Map<String, Integer> nextNode) {
        this.nextNode = nextNode;
    }

}

这里代码挺多,但是大部分都是去初始化图的结构了,真正的操作胆码数量还是可以查看的。

点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
1.6万
获赞与收藏
380

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消