breadth-first search
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 TopologicalSorting {
//定义顶点信息
private static class Vertex {
@Getter @Setter
private int indegree; //入度
@Getter @Setter
private String name ; //顶点信息
//广度优先搜索新增字段
@Getter @Setter
private int deepPath = Integer.MIN_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 {
public Map<Vertex, Set<Vertex>> relMap=new HashMap<>(); //顶点与节点关系
public Set<Vertex> vertices=new HashSet<>(); //所有节点信息
//添加顶点关系图
public boolean addRelVertex(Vertex start, Vertex end) {
//根据name判断重复
vertices.add(start);
vertices.add(end);
Set<Vertex> adjcents=relMap.get(start); //相邻节点信息
if (CollectionUtils.isEmpty(adjcents)) {
adjcents = new HashSet<>();
}
if (adjcents.contains(end)) {
return false;
}
adjcents.add(end);
int indegree=end.getIndegree();
end.setIndegree(++indegree); //入度+1
relMap.put(start, adjcents);
return true;
}
}
public static List<Vertex> bfs_sort(TopoGraph topoGraph, Vertex firstRoot) {
Queue<Vertex> knownQueue=new LinkedList<>();
List<Vertex> resultList=new ArrayList<>();
firstRoot.setDeepPath(0); //设置深度为0
firstRoot.setIsKnown(true); //设置为已探知
knownQueue.add(firstRoot);
while (!knownQueue.isEmpty()) {
Vertex knownVertex=knownQueue.poll();
resultList.add(knownVertex);
Set<Vertex> adjacents=topoGraph.relMap.get(knownVertex); //相邻节点信息
if (!CollectionUtils.isEmpty(adjacents)) {
for (Vertex adj : adjacents) {
if (!adj.isKnown()) {
//深度+1 表明为已探知,指定上一个节点
adj.setDeepPath(knownVertex.getDeepPath() + 1);
adj.setIsKnown(true);
adj.setPreShortVertex(knownVertex);
knownQueue.add(adj);
}
}
}
}
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();
}
}
if (count != resultList.size()) {
throw new RuntimeException(" 闭环");
}
return resultList;
}
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);
topoGraph.addRelVertex(vertexA, vertexC);
topoGraph.addRelVertex(vertexC, vertexD);
topoGraph.addRelVertex(vertexB, vertexD);
topoGraph.addRelVertex(vertexB, vertexE);
topoGraph.addRelVertex(vertexD, vertexE);
//广度优先搜索
List<Vertex> vertices=bfs_sort(topoGraph, vertexA);
printShortPath(vertices);
}
//打印结果 到达 a b c d e 的最短路径
//A:0
//B:1<----A:0
//C:1<----A:0
//D:2<----B:1<----A:0
//E:2<----B:1<----A:0
}