package com.ygy.test.sort;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import java.util.*;
/**
* Created by guoyao on 2017/10/11.
*/
//拓扑排序
public class Dijkstra {
//定义顶点信息
private static class Vertex {
@Getter @Setter
private int indegree; //入度
@Getter @Setter
private String name ; //顶点信息
//广度优先搜索新增字段
@Getter @Setter
private int deepPath = Integer.MAX_VALUE ; //路径深度 初始化为最小
@Getter @Setter
private Boolean isKnown = false ; //路口是否已探 初始化为false
@Getter @Setter
private Vertex preShortVertex ;
public boolean isKnown() {
return isKnown ;
}
public Vertex(String name) {
this.name=name;
indegree = 0 ; //初始入度为0
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Vertex vertex=(Vertex) o;
return name.equals(vertex.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
//定义拓扑关系图
private static class TopoGraph {
//dijkstra 修改关系为map 带入权重
public Map<Vertex, Map<Vertex,Integer>> relMap=new HashMap<>(); //顶点与节点关系
public Set<Vertex> vertices=new HashSet<>(); //所有节点信息
//添加顶点关系图
public boolean addRelVertex(Vertex start, Vertex end,Integer weight) {
//根据name判断重复
vertices.add(start);
vertices.add(end);
Map<Vertex,Integer> adjcents=relMap.get(start); //相邻节点信息
if (CollectionUtils.isEmpty(adjcents)) {
adjcents = new HashMap<>();
}
if (adjcents.containsKey(end)) {
return false;
}
adjcents.put(end,weight);
int indegree=end.getIndegree();
end.setIndegree(++indegree); //入度+1
relMap.put(start, adjcents);
return true;
}
}
public static List<Vertex> dijkstra(TopoGraph topoGraph,Vertex root) {
PriorityQueue<Vertex> knownQueue=new PriorityQueue<>(
(x,y)-> x.getDeepPath() - y.getDeepPath() > 0 ? 1: - 1
);
List<Vertex> resultList=new ArrayList<>();
root.setIsKnown(true);
root.setDeepPath(0);
knownQueue.add(root);
//最小堆结构,构造最近数据
while (!knownQueue.isEmpty()) {
Vertex minVertex=knownQueue.remove(); //移出最小deep节点
minVertex.setIsKnown(true); //标记为已知
resultList.add(minVertex);
Map<Vertex, Integer> relAdj=topoGraph.relMap.get(minVertex);
if (!CollectionUtils.isEmpty(relAdj)) {
for (Vertex vertex : relAdj.keySet()) {
if (!vertex.isKnown()) {
Integer weight=relAdj.get(vertex);
//比较已有的deep值,找出最小路线
if (minVertex.getDeepPath() + weight < vertex.getDeepPath()) {
knownQueue.remove(vertex); //移出已有的
vertex.setDeepPath((weight + minVertex.getDeepPath()));
knownQueue.add(vertex);
vertex.preShortVertex=minVertex;
}
}
}
}
}
return resultList;
}
public static void printShortPath(List<Vertex> list) {
if (CollectionUtils.isEmpty(list)) {
return;
}
for (Vertex vertex : list) {
int count = 0 ;
while (vertex != null) {
if (count != 0) {
System.out.print("<----");
}
System.out.print(vertex.getName()+ ":"+ vertex.getDeepPath());
vertex = vertex.preShortVertex;
count ++ ;
}
System.out.println();
}
}
public static void main(String[] args) throws Exception {
Vertex vertexA=new Vertex("A");
Vertex vertexB=new Vertex("B");
Vertex vertexC=new Vertex("C");
Vertex vertexD=new Vertex("D");
Vertex vertexE=new Vertex("E");
TopoGraph topoGraph=new TopoGraph();
topoGraph.addRelVertex(vertexA, vertexB,5);
topoGraph.addRelVertex(vertexA, vertexC,2);
topoGraph.addRelVertex(vertexC, vertexD,3);
topoGraph.addRelVertex(vertexC, vertexB,2);
topoGraph.addRelVertex(vertexB, vertexD,2);
topoGraph.addRelVertex(vertexB, vertexE,15);
topoGraph.addRelVertex(vertexD, vertexE,4);
printShortPath(dijkstra(topoGraph, vertexA));
}
//A:0
//C:2<----A:0
//B:4<----C:2<----A:0
//D:5<----C:2<----A:0
//E:9<----D:5<----C:2<----A:0
}
拓扑排序-Dijkstra算法
最新推荐文章于 2022-10-26 22:43:51 发布