1. 图的表示
图用 G = (V,E)表示。V表示顶点集,E表示每条边。
n = |V|, m = |E|, 表示有 n个顶点,m条边。
顶点n 与 边数m 的关系:m ——(n-1 ~ n^2)之间;
2. 图的分类
图根据边有无方向,分为有向图、无向图;
图根据顶点数与边数的关系,分为稀疏图、稠密图。
顶点数n与边数m大致呈线性关系的为稀疏图,顶点数n与边数m大致呈平方关系的为稠密图(m~n^2)。
3. 图的表示
可以用邻接列表、邻接矩阵来表示图。
稀疏图一般用邻接列表(占用空间大致为m+n),稠密图用邻接矩阵表示(占用空间为n^2,稀疏图如果用邻接矩阵表示太浪费空间,所以邻接矩阵一般只表示小的稀疏图或者稠密图)。
4. 图的遍历
宽度优先、深度优先遍历
- 宽度优先遍历 BFS Breadth First Search
- 深度优先遍历 DFS Depth First Search
示例图A:
示例图B:
5. 源码
遍历结果效果图:
5.1 图的邻接列表表示
package graph;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/*************************************
*Class Name: Graph
*Description: <图的邻接列表表示方法>
*@author: Seminar
*@create: 2021/5/11
*@since 1.0.0
*************************************/
public class Graph {
private List<String> vList;
private Map<String, List<String>> eList;
public Graph(List<String> vList, Map<String, List<String>> eList) {
this.vList = vList;
this.eList = eList;
}
public List<String> getvList() {
return vList;
}
public Map<String, List<String>> geteList() {
return eList;
}
public static Graph initA() {
List<String> vList = new ArrayList();
Map<String, List<String>> eList = new HashMap();
vList.add("s");
vList.add("a");
vList.add("b");
vList.add("c");
vList.add("d");
vList.add("e");
List<String> sList = new ArrayList<>();
sList.add("a");
sList.add("b");
eList.put("s", sList);
List<String> aList = new ArrayList<>();
aList.add("s");
aList.add("c");
eList.put("a", aList);
List<String> bList = new ArrayList<>();
bList.add("s");
bList.add("c");
bList.add("d");
eList.put("b", bList);
List<String> cList = new ArrayList<>();
cList.add("a");
cList.add("b");
cList.add("d");
cList.add("e");
eList.put("c", cList);
List<String> dList = new ArrayList<>();
dList.add("b");
dList.add("c");
dList.add("e");
eList.put("d", dList);
List<String> e1List = new ArrayList<>();
e1List.add("c");
e1List.add("d");
eList.put("e", e1List);
return new Graph(vList, eList);
}
public static Graph initB() {
List<String> vList = new ArrayList();
Map<String, List<String>> eList = new HashMap();
vList.add("1");
vList.add("2");
vList.add("3");
vList.add("4");
vList.add("5");
vList.add("6");
vList.add("7");
vList.add("8");
List<String> oneList = new ArrayList<>();
oneList.add("2");
oneList.add("3");
eList.put("1", oneList);
List<String> twoList = new ArrayList<>();
twoList.add("1");
twoList.add("4");
twoList.add("5");
eList.put("2", twoList);
List<String> threeList = new ArrayList<>();
threeList.add("1");
threeList.add("6");
threeList.add("7");
eList.put("3", threeList);
List<String> fourList = new ArrayList<>();
fourList.add("2");
fourList.add("8");
eList.put("4", fourList);
eList.put("5", fourList);
List<String> sixList = new ArrayList<>();
sixList.add("3");
eList.put("6", sixList);
eList.put("7", sixList);
List<String> eightList = new ArrayList<>();
eightList.add("4");
eightList.add("5");
eList.put("8", eightList);
return new Graph(vList, eList);
}
}
5.1 邻接列表宽度优先、深度优先遍历
package graph;
import java.util.*;
/*************************************
*Class Name: GenericSearch
*Description: <基本遍历查找>
*@author: Seminar
*@create: 2021/5/11
*@since 1.0.0
*************************************/
public class GenericSearch {
/**
* Breadth First Search 宽度优先遍历
*
* @param graph 无向图
* @param first 起点
*/
public static void BFS(Graph graph, String first) {
// 宽度优先遍历
Queue<String> queue = new ArrayDeque<>();
queue.add(first);
Map<String, Boolean> map = new HashMap<>();
for (String str : graph.getvList()) {
map.put(str, Boolean.FALSE);
}
String bfsStr = "BFS: ";
while (queue.size() > 0) {
String v = queue.poll();
if (map.get(v) == Boolean.TRUE) {
continue;
}
bfsStr += v + " -> ";
// System.out.print(v + " -> ");
// 标记为“已探索”
map.put(v, Boolean.TRUE);
for (String w : graph.geteList().get(v)) {
queue.add(w);
}
}
System.out.println(bfsStr.substring(0, bfsStr.length() - 4));
}
/**
* Depth First Search 深度优先遍历
*
* @param graph 无向图
* @param first 起点
*/
public static void DFS(Graph graph, String first) {
Queue<String> queue = new ArrayDeque<>();
queue.add(first);
Deque<String> deque = new ArrayDeque<>();
deque.add(first);
Map<String, Boolean> map = new HashMap<>();
for (String str : graph.getvList()) {
map.put(str, Boolean.FALSE);
}
// 深度优先遍历
String dfsStr = "DFS: ";
String vv = "";
while (deque.size() > 0) {
vv = deque.poll();
for (String w : graph.geteList().get(vv)) {
while (queue.size() > 0) {
vv = queue.poll();
if (map.get(vv) == Boolean.TRUE) {
continue;
}
dfsStr += vv + " -> ";
// System.out.println(vv);
// 标记为“已探索”
map.put(vv, Boolean.TRUE);
for (String w1 : graph.geteList().get(vv)) {
if (map.get(w1) == Boolean.TRUE) {
continue;
}
queue.add(w1);
deque.add(w1);
break;
}
}
if (map.get(w) == Boolean.TRUE) {
continue;
} else {
queue.add(w);
deque.add(w);
}
}
}
System.out.println(dfsStr.substring(0, dfsStr.length() - 4));
}
public static void main(String[] args) {
Graph graphA = Graph.initA();
String first = "s";
System.out.println("图A:");
BFS(graphA, first);
DFS(graphA, first);
System.out.println();
Graph graphB = Graph.initB();
first = "1";
System.out.println("图B:");
BFS(graphB, first);
DFS(graphB, first);
}
}