图表示
无向图表示
有向图表示
; 个人偏向于邻接链表表示法,比较简单方便,占用空间也不大。
图遍历
广度优先搜索
每个结点初始颜色为白色,被发现后,变为灰色,并将其插入队列,其邻接链表扫描完成后变为黑色;
深度优先搜索
与广度优先基本相同,只是不再使用队列保存未扫描结点,而改为递归深度扫描。
#代码(包括图表示、BFS、DFS)
import java.util.*;
public class Graph {
private enum Color {
WHITE(0, "white"),
GRAY(1, "gray"),
BLACK(2, "black");
private int value;
private String desc;
Color(int value, String desc) {
this.value = value;
this.desc = desc;
}
}
static class Node {
public Node pre;
public List<Node> next;
public Color color;
// BFS中作为与指定节点的度数,DFS中作为首次访问该节点的时间
public int d;
// 深度优先遍历中使用,节点深度遍历访问完成的时间,与其连接的结点都已经访问过
public int f;
public int value;
}
/**
* 生成无向图,结点数量为count
* 使用邻接链表表示图
* @param count
* @return
*/
private static List<Node> generateUndirectedGraph(int count) {
// 控制结点与其他结点连接的概率
int p = 3;
int bound = 10;
List<Node> allNode = new ArrayList<>();
for (int i = 0; i < count; i++) {
Node node = new Node();
node.value = i;
allNode.add(node);
}
Random random = new Random();
for (int i = 0; i < count - 1; i++) {
for (int j = 1; j < count; j++) {
if (random.nextInt(bound) < p) {
List<Node> iNextList = allNode.get(i).next;
if (iNextList == null) {
iNextList = new ArrayList<>();
allNode.get(i).next = iNextList;
}
iNextList.add(allNode.get(j));
List<Node> jNextList = allNode.get(j).next;
if (jNextList == null) {
jNextList = new ArrayList<>();
allNode.get(j).next = jNextList;
}
jNextList.add(allNode.get(i));
}
}
}
return allNode;
}
/**
* 生成有向图,结点数量为count
* 使用邻接链表表示图
*
* @param count
* @return
*/
private static List<Node> generateDirectedGraph(int count) {
// 控制结点与其他结点连接的概率
int p = 3;
int bound = 10;
List<Node> allNode = new ArrayList<>();
for (int i = 0; i < count; i++) {
Node node = new Node();
node.value = i;
allNode.add(node);
}
Random random = new Random();
for (int i = 0; i < count; i++) {
for (int j = 0; j < count; j++) {
if (random.nextInt(bound) < p) {
List<Node> iNextList = allNode.get(i).next;
if (iNextList == null) {
iNextList = new ArrayList<>();
allNode.get(i).next = iNextList;
}
iNextList.add(allNode.get(j));
}
}
}
return allNode;
}
private static void printGraph(List<Node> allNode) {
for (Node node : allNode) {
if (node.next != null && node.next.size() != 0) {
StringBuilder next = new StringBuilder();
for (Node n : node.next) {
next.append(n.value);
next.append(",");
}
StringBuilder printString =
new StringBuilder("node : " + node.value + ", next : " + next.toString() +
" d : " + node.d + ", f : " + node.f);
if (node.color != null) {
printString.append(", color : " + node.color.desc);
}
System.out.println(printString.toString());
} else {
System.out.println("node : " + node.value + ", no next");
}
}
}
/**
* 每个结点初始颜色为白色,被发现后,变为灰色,并将其插入队列,其邻接链表扫描完成后变为黑色;
* 队列管理灰色结点集合
*
* @param allNode
* @param s
*/
private static void bfs(List<Node> allNode, Node s) {
if (!allNode.contains(s)) {
return;
}
int count = allNode.size();
for (Node node : allNode) {
if (node.equals(s)) {
continue;
}
node.color = Color.WHITE;
node.d = count + 1;
node.pre = null;
}
s.color = Color.GRAY;
s.d = 0;
s.pre = null;
Queue<Node> q = new LinkedList<>();
q.add(s);
Node u;
while (!q.isEmpty()) {
u = q.poll();
if (u.next != null && u.next.size() != 0) {
for (Node v : u.next) {
if (v.color == Color.WHITE) {
v.color = Color.GRAY;
v.d = u.d + 1;
v.pre = u;
q.add(v);
}
}
}
u.color = Color.BLACK;
}
}
private static int time = 0;
/**
* 每个结点初始颜色为白色,被发现后,变为灰色,其邻接链表扫描完成后变为黑色;
* 深度优先搜索完成后,前驱子图构成的深度优先搜索树构成深度优先搜索森林
* @param allNode
*/
private static void dfs(List<Node> allNode) {
for (Node node : allNode) {
node.color = Color.WHITE;
node.pre = null;
}
for (Node node : allNode) {
if (node.color.equals(Color.WHITE)) {
dfsVisit(allNode, node);
}
}
}
private static void dfsVisit(List<Node> allNode, Node u) {
time++;
u.d = time;
u.color = Color.GRAY;
if (u.next != null && u.next.size() != 0) {
for (Node v : u.next) {
if (v.color == Color.WHITE) {
v.pre = u;
dfsVisit(allNode, v);
}
}
}
u.color = Color.BLACK;
time++;
u.f = time;
}
public static void main(String[] args) {
int count = 10;
List<Node> undirectedGraph = generateUndirectedGraph(count);
System.out.println("=====================undirectedGraph====================");
printGraph(undirectedGraph);
bfs(undirectedGraph, undirectedGraph.get(0));
System.out.println("=====================BFS start with 0====================");
printGraph(undirectedGraph);
List<Node> directedGraph = generateDirectedGraph(count);
System.out.println("=====================directedGraph====================");
printGraph(directedGraph);
dfs(directedGraph);
System.out.println("=====================DFS====================");
printGraph(directedGraph);
}
}
参考文档
《算法导论》