/** * 初始化起始点 <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); // 向外一层层递归,直至所有顶点被遍历 }
/** 测试方法 */ @org.junit.Test public void test() { MapBuilder<String> mapBuilder = new Maps.MapBuilder<String>().create(); // 构建节点 mapBuilder.addNode(Maps.Node.valueOf("A")); mapBuilder.addNode(Maps.Node.valueOf("B")); mapBuilder.addNode(Maps.Node.valueOf("C")); mapBuilder.addNode(Maps.Node.valueOf("D")); mapBuilder.addNode(Maps.Node.valueOf("E")); mapBuilder.addNode(Maps.Node.valueOf("F")); mapBuilder.addNode(Maps.Node.valueOf("G")); mapBuilder.addNode(Maps.Node.valueOf("H")); mapBuilder.addNode(Maps.Node.valueOf("I")); // 构建路径 mapBuilder.addPath("A", "B", 1); mapBuilder.addPath("A", "F", 2); mapBuilder.addPath("A", "D", 4); mapBuilder.addPath("A", "C", 1); mapBuilder.addPath("A", "G", 5); mapBuilder.addPath("C", "G", 3); mapBuilder.addPath("G", "H", 1); mapBuilder.addPath("H", "B", 4); mapBuilder.addPath("B", "F", 2); mapBuilder.addPath("E", "F", 1); mapBuilder.addPath("D", "E", 1); mapBuilder.addPath("H", "I", 1); mapBuilder.addPath("C", "I", 1); // 构建全局Map Maps<String> map = mapBuilder.build(); // 创建路径搜索器(每次搜索都需要创建新的MapSearcher) MapSearcher<String> searcher = new MapSearcher<String>(); // 创建关闭节点集合 Set<String> closeNodeIdsSet = new HashSet<String>(); closeNodeIdsSet.add("C"); // 设置初始节点 searcher.init("A", map, closeNodeIdsSet); // 获取结果 SearchResult<String> result = searcher.getResult("G"); System.out.println(result); // test.printPathInfo(); }