定义
// 节点
public class Node {
public int val;
public int in; // 入度
public int out; // 出度
public ArrayList<Node> nexts; // 邻接节点
public ArrayList<Edge> edges; // 邻接边
public Node(int val) {
this.val = val;
this.in = 0;
this.out = 0;
this.nexts = new ArrayList<>();
this.edges = new ArrayList<>();
}
}
// 边
public class Edge {
public int weigth;
public Node from;
public Node to;
public Edge(int weigth, Node from, Node to) {
this.weigth = weigth;
this.from = from;
this.to = to;
}
}
// 图
public class Graph {
HashMap<Integer,Node> nodes; // key:节点编号 value:节点
HashSet<Edge> edges;
public Graph(){
this.nodes=new HashMap<Integer, Node>();
this.edges=new HashSet<Edge>();
}
}
/** 根据数据 生成一张图. matrix的列值对应 [weight,from,to] */
public static Graph createGarph(Integer[][] matrix){
Graph graph=new Graph();
for(int i=0;i< matrix.length;i++){
Integer weight=matrix[i][0];
Integer from=matrix[i][1];
Integer to=matrix[i][2];
//判断是图中是否存在该节点
if(!graph.nodes.containsKey(from)){
graph.nodes.put(from,new Node(from));
}
if(!graph.nodes.containsKey(to)){
graph.nodes.put(to,new Node(to));
}
Node fromNode = graph.nodes.get(from);
Node toNode = graph.nodes.get(to);
Edge edge = new Edge(weight, fromNode, toNode);
fromNode.out++;
fromNode.nexts.add(toNode);
fromNode.edges.add(edge);
toNode.in++;
graph.edges.add(edge);
}
return graph;
}
广度优先遍
利用队列先进先出的特点。遍历一个节点时,就获取其所有的邻接点,判断该邻接节点是否进入过set,如果未进入,加入到队列中并向set注册。。如果进入,不理它。
public void BFS(Node node){
HashSet<Node> set=new HashSet<>();// 注册中心,遍历过的节点先进入该集合中。
Queue<Node> queue=new LinkedList<>();
queue.add(node);
set.add(node);
while (!queue.isEmpty()){
Node n = queue.poll();
System.out.println(n.val);
for(Node no:n.nexts){
if (!set.contains(no)){
queue.add(no);
set.add(no);
}
}
}
}
深度优先遍历
利用栈以及set。 选择的路不同,会导致不同的结果。 节点会被弹入又弹出。需要利用栈的特性!!向注册中心添加的时候,就打印出来。
public static void DFS(Node node){
HashSet<Node> set=new HashSet<>();
Stack<Node> stack=new Stack<>();
stack.push(node);
set.add(node);
System.out.println(node.val);
while(!stack.isEmpty()){
Node pop = stack.pop();
for(Node n:pop.nexts){
if(!set.contains(n)){
stack.push(pop);
stack.push(n);
set.add(n);
System.out.println(n.val);
break;
}
}
}
}
拓扑排序
[ 有向且无环的图才可 ]
给定一张图,找到所有入度为0的节点 [这种节点只是from节点,不会是to节点。],加入zeroInQueue。移除节点的时候,将与该节点相邻的所有节点的入度减1,会有新的入度为0的节点出现。
public void topoLogySort(Graph graph){
HashMap<Node,Integer> map=new HashMap<>();
Queue<Node> zeroInQueue=new LinkedList<>();
for(Node n:graph.nodes.values()){
map.put(n,n.in);
if(n.in==0){ //刚开始时,入度为0的节点先加入队列中。
zeroInQueue.add(n);
}
}
while (!zeroInQueue.isEmpty()){
Node poll = zeroInQueue.poll();
System.out.println(poll.val);
for(Node next: poll.nexts){
map.put(next,map.get(next)-1);
if(map.get(next)==0){
zeroInQueue.add(next);
}
}
}
}