/** * 初始化起始点 <br> * 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离" [例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。 * * @param source 起始节点的Id * @param map 全局地图 * @param closeSet 已经关闭的节点列表 * @return */ @SuppressWarnings("unchecked") public Maps.Node<T> init(T source, Maps<T> map, Set<T> closeSet) { Map<T, Maps.Node<T>> nodeMap = map.getNodes(); Maps.Node<T> startNode = nodeMap.get(source); // 将初始节点放到close close.add(startNode); // 将其他节点放到open for (Maps.Node<T> node : nodeMap.values()) { if (!closeSet.contains(node.getId()) && !node.getId().equals(source)) { this.open.add(node); } } // 初始路径 T startNodeId = startNode.getId(); for (Entry<Maps.Node<T>, Integer> entry : startNode.getChilds().entrySet()) { Maps.Node<T> node = entry.getKey(); if (open.contains(node)) { T nodeId = node.getId(); path.put(node, entry.getValue()); pathInfo.put(nodeId, new ArrayList<T>(Arrays.asList(startNodeId, nodeId))); } } for (Maps.Node<T> node : nodeMap.values()) { if (open.contains(node) && !path.containsKey(node)) { path.put(node, Integer.MAX_VALUE); pathInfo.put(node.getId(), new ArrayList<T>(Arrays.asList(startNodeId))); } } this.startNode = startNode; this.map = map; return startNode; }
/** * 递归Dijkstra * * @param start 已经选取的最近节点 */ protected void computePath(Maps.Node<T> start) { // 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。 Maps.Node<T> nearest = getShortestPath(start); if (nearest == null) { return; } // 更新U中各个顶点到起点s的距离。 // 之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离; // 例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。 close.add(nearest); open.remove(nearest); // 已经找到结果 if (nearest == this.targetNode) { return; } Map<Maps.Node<T>, Integer> childs = nearest.getChilds(); for (Map.Entry<Maps.Node<T>, Integer> entry : childs.entrySet()) { Maps.Node<T> child = entry.getKey(); if (open.contains(child)) { // 如果子节点在open中 Integer newCompute = path.get(nearest) + entry.getValue(); if (path.get(child) > newCompute) { // 之前设置的距离大于新计算出来的距离 path.put(child, newCompute); List<T> path = new ArrayList<T>(pathInfo.get(nearest.getId())); path.add(child.getId()); pathInfo.put(child.getId(), path); } } } // computePath(start);// 重复执行自己,确保所有子节点被遍历 computePath(nearest); // 向外一层层递归,直至所有顶点被遍历 }