图有两种表示方法:
1. 邻接矩阵表示法:用二维数组的结构来存储图,优点是利用数组下标便于计算,缺点是比较浪费空间
2. 邻接表表示法:用一维数组加链表的方式来存储图,优点是节省存储空间,缺点是不便于操作
图的两种常用算法:
1.深度优先遍历
深度优先遍历借助于队列来实现
2. 广度优先遍历
广度优先搜索借助于回溯算法实现
具体代码如下:
// 用邻接表的方式定义图
public class Graph {
private int v;
private LinkedList adj[];
public Graph(int v){
this.v = v;
adj = new LinkedList[v];
for(int i = 0; i < v; i++){
adj[i] = new LinkedList<>();
}
}
public void addEdge(int s, int t){
adj[s].add(t);
adj[t].add(s);
}
// 广度优先遍历
public void bfs(int s, int t){
if(s == t) return;
boolean visited [] = new boolean[v];
visited[s] = true;
Queue queue = new LinkedList<>();
queue.add(s);
int [] prev = new int[v];
for(int i = 0; i < v; i++){
prev[i] = -1;
}
while(queue.size() != 0){
int w = queue.poll();
for(int i = 0; i < adj[w].size(); i++){
int q = adj[w].get(i);
if(!visited[q]){
prev[q] = w;
if(q == t){
printPrev(prev, s, t);
return;
}
}
visited[q] = true;
queue.add(q);
}
}
}
// 打印出路径
public void printPrev(int prev[], int s, int t){
if(prev[t] != -1 && s != t){
printPrev(prev, s, prev[t]);
}
System.out.print(t + " ");
}
// 深度优先搜索
boolean found = false;
public void dfs(int s, int t){
found = false;
boolean visited[] = new boolean[v];
visited[s] = true;
int [] prev = new int [v];
for(int i = 0; i < v; i++){
prev[i] = -1;
}
recurDfs(s, t, visited, prev);
printPrev(prev, s, t);
}
// 利用回溯的思想来实现深度遍历
public void recurDfs(int w, int t, boolean [] visited, int prev[]){
if(found == true) return;
visited[w] = true;
if(w == t){
found = true;
return;
}
for(int i = 0; i < adj[w].size(); i++){
int q = adj[w].get(i);
if(!visited[q]){
prev[q] = w;
recurDfs(q, t, visited, prev);
}
}
}
}