一个图有边和结点,边包含权重、入结点和出结点,结点包含值、入度、出度、next结点集、和边的集合。可以用以下代码表示:
public class Edge {
public int weight;
public Node from;
public Node to;
public Edge(int weight, Node from, Node to) {
this.weight = weight;
this.from = from;
this.to = to;
}
}
public class Node {
public int value;
public int in;
public int out;
public ArrayList<Node> nexts;
public ArrayList<Edge> edges;
public Node(int value) {
this.value = value;
in = 0;
out = 0;
nexts = new ArrayList<>();
edges = new ArrayList<>();
}
}
public class Graph {
public HashMap<Integer, Node> nodes;
public HashSet<Edge> edges;
public Graph() {
nodes = new HashMap<>();
edges = new HashSet<>();
}
}
而生成图时,可以提供一个二维数组,每个子数组为边的权重、边的入结点和出结点,可以用以下代码表示:
public class GraphGenerator {
public static Graph createGraph(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 newEdge = new Edge(weight, fromNode, toNode);
fromNode.nexts.add(toNode);
fromNode.out++;
toNode.in++;
fromNode.edges.add(newEdge);
graph.edges.add(newEdge);
}
return graph;
}
}
图生成后就可以来看宽度优先遍历和深度优先遍历了。
宽度优先遍历:用队列和set来实现。思想是按层遍历,把根结点输出,把根节点的所有next结点放进队列,一次输出next结点同时把他的所有next结点放进队列就完成了。set用来表示是否打印过。代码如下所示:
public class BFS {
public static void bfs(Node node) {
if(node == null) {
return;
}
Queue<Node> queue = new LinkedList<>();
HashSet<Node> set = new HashSet<>();
queue.add(node);
set.add(node);
while(!queue.isEmpty()) {
Node cur = queue.poll();
System.out.println(cur.value);
for(Node next : cur.nexts) {
if(!set.contains(next)) {
set.add(next);
queue.add(next);
}
}
}
}
}
深度优先遍历:用栈和set来实现。思想是先遍历根节点的一个next结点的所有next结点,遍历完之后再遍历根节点的其他next结点。代码如下所示:
public class DFS {
public static void dfs(Node node) {
if(node == null) {
return;
}
Stack<Node> stack = new Stack<>();
HashSet<Node> set = new HashSet<>();
stack.add(node);
set.add(node);
System.out.println(node.value);
while(!stack.isEmpty()) {
Node cur = stack.pop();
for(Node next : cur.nexts) {
if(!set.contains(next)) {
stack.push(cur);
stack.push(next);
set.add(next);
System.out.println(next.value);
break;//注意这是就放进根节点和最左边的结点就break
}
}
}
}
}