Dijkstra求权重图最短路径

在这里插入图片描述
把Dijkstra算法逻辑梳理了一下,其实原理也很清晰.

打个比方:

有很多房间,每个房间有若干扇门(门上有房号)可以通向另一个房间,而打开每扇门的成本是不一样的。我们的目标是按照一定规律去尽可能的探索更多的房间。
第一步: 我们找到当前房间中打开成本最低的那扇门。
第二步:我们进到新的房间,这个时候我们又会看到很多新的门。注意这里每扇门是有房号的,新房间的门的房号可能和之前其他房间遇到的门房号是一样的(通向同一个房间)。遇到这种情况我们需要去判断是从新房间的门打开成本低还是之前打开的成本低。更新所有能开的门的打开成本
第三步:从所有能开的门中找到成本最低的打开
重复第二步,直到遇到目标房间,搜索结束

import java.util.HashMap;
import java.util.LinkedList;
import java.util.TreeMap;
import java.util.Map.Entry;

public class Dijkstra {
	private static void Log(String value) {
		System.out.print(value);	
	}

	private static void Logln(String value) {
		System.out.println(value);		
	}

	public static void main(String[] args) {
		           // a         b         c         d         e         f
        int[][] G = {{0,        7,        12,       DIST_NAN, DIST_NAN, DIST_NAN},  // a
                     {7,        0,        DIST_NAN, 3,        DIST_NAN, 10},        // b
	                 {12,       DIST_NAN, 0,        12,       18,       DIST_NAN},  // c
		             {DIST_NAN, 3,        12,       3,        DIST_NAN, 8},         // d
			         {DIST_NAN, DIST_NAN, 18,       DIST_NAN, 0,        6},         // e
				     {DIST_NAN, 10,       DIST_NAN, 8,        6,        0}};        // f

		char[] nodeName = {'a', 'b', 'c', 'd', 'e', 'f'};

	    int start = 4;
		int end = 0;

		Logln("find path from " + nodeName[start] + " to " + nodeName[end]);

		LinkedList<Integer> ret = new Dijkstra().find(G, 6, start, end);

		if (ret != null) {
			while(!ret.isEmpty()) {
				Log(">" + nodeName[ret.removeLast()]);	
			}
		}
	}

	private static final int DIST_NAN = 8888;

    private LinkedList<Integer> find(int[][] graph, int size, int vStart, int vEnd) {
        int dist, minDist;
        int nodeIndex, newNodeIndex;
        Node node;
        HashMap<Integer, Node> unMarkedNodes = new HashMap<>();
        HashMap<Integer, Node> markedNodes = new HashMap<>();

        for (int i = 0; i < size; i++) {
            if (vStart == i) {
                continue;
            } else {
                unMarkedNodes.put(i, new Node(vStart, graph[vStart][i]));
            }
        }

		// find min dist
		minDist = DIST_NAN;
		newNodeIndex = -1;

		for (HashMap.Entry<Integer, Node> entry: unMarkedNodes.entrySet()) {
			dist = entry.getValue().dist;
			if (minDist > dist) {
				newNodeIndex = entry.getKey();
				minDist = dist;
			}
		}

        while(true) {
            // Can not find path from vStart to vEnd.
            if (newNodeIndex == -1) {
                return null;
            }

			// remove new node from unmarked nodes.
            node = unMarkedNodes.remove(newNodeIndex);

			// add the new node into marked nodes.
            markedNodes.put(newNodeIndex, node);

			// If the new node is the target node, it means we have found the path with lowest distance from vStart to vEnd.
            if (newNodeIndex == vEnd) {
                break;
            }

			minDist = DIST_NAN;
			nodeIndex = -1;

            // update unmarked nodes, and find out the min distance from marked nodes(Graph) to the unmarked nodes(Graph).
            for (HashMap.Entry<Integer, Node> entry: unMarkedNodes.entrySet()) {
                int index = entry.getKey();
                dist = graph[newNodeIndex][index] + node.dist;

                // has a lower distance, if we access the node with new added node.
                if (dist < entry.getValue().dist) {
                    entry.getValue().prev = newNodeIndex;
                    entry.getValue().dist = dist;
                } else {
					dist = entry.getValue().dist;
				}

				// update min dist.
				if (dist < minDist) {
					nodeIndex = index;
					minDist = entry.getValue().dist;
				}
            }	

			// We found a new node from unmared nodes which has the lowest distance to the marked graph.
			// If it is equal to -1, That means no new node was found.
			newNodeIndex = nodeIndex;
        }

        node = markedNodes.get(vEnd);

        LinkedList<Integer> list = new LinkedList<>();

		if (node != null) {
			list.add(vEnd);
			while (node != null) {
				list.add(node.prev);
				node = markedNodes.get(node.prev);
			}
	    }

        return list;
    }

    private static class Node {
        int prev;
        int dist;

        public Node(int prev, int dist) {
            this.prev = prev;
            this.dist = dist;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值