参考:
大佬博客:https://www.cnblogs.com/xiaohuiduan/p/11352209.html
https://blog.csdn.net/leonliu1995/article/details/78509599
书籍:算法4
/*
* @Description:
* @Author: YPY
* @Date: 2021-11-21 23:17:54
* @LastEditTime: 2021-11-22 23:08:36
* @LastEditors: YPY
* @Reference:
*/
package com.ypy.suanfa;
import java.util.ArrayList;
import java.util.List;
public class Graph {
private static final String NEWLINE = System.getProperty("line.separator");
private final int V;
private int E;
private List<Integer>[] adj;
public Graph(int V) {
this.V = V;
this.E = 0;
adj = (List<Integer>[]) new List[V];
for (int v = 0; v < V; v++) {
adj[v] = new ArrayList<Integer>(V);
}
}
public int V() {
return V;
}
public int E() {
return E;
}
/**
* 添加边,根据邻接表的含义,一条边连接两个顶点,在顶点A的邻接表放入顶点B,在顶点B的邻接表放入顶点A,则构成边。
* @param v
* @param w
*/
public void addEdge(int v, int w) {
adj[v].add(w);
adj[w].add(v);
//边的个数加1
E++;
}
public Iterable<Integer> adj(int v) {
return adj[v];
}
public String toString() {
StringBuilder s = new StringBuilder();
s.append(V + " vertices, " + E + " edges " + NEWLINE);
for (int v = 0; v < V; v++) {
s.append(v + ": ");
for (int w : adj[v]) {
s.append(w + " ");
}
s.append(NEWLINE);
}
return s.toString();
}
}
package com.ypy.suanfa;
/*
* @Description: 基于深度优先的路径查找。
* @Author: YPY
* @Date: 2021-11-21 23:12:10
* @LastEditTime: 2021-11-24 10:50:59
* @LastEditors: YPY
* @Reference:
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
public class DFS {
private boolean[] marked;
// 从A到B经历的边的条数
private int[] edgeTo;
// 起点
private final int s;
private int count;
public DFS(Graph G, int s) {
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
count = 0;
dfs(G, s);
}
/**
* 深度优先
*
* @param G
* @param v
*/
private void dfs(Graph G, int v) {
// 把v点记为被标记过,后面就不会遍历到v
marked[v] = true;
//
count++;
for (int w : G.adj(v)) {
if (!marked[w]) {
dfs(G, w);
}
}
}
public boolean marked(int w) {
return marked[w];
}
public int getcount() {
return count;
}
public boolean hasPathTo(int v) {
return marked(v);
}
public Iterable<Integer> search(Graph G, int s) {
DFS dfs = new DFS(G, s);
List<Integer> list = new ArrayList<Integer>(dfs.getcount());
for (int v = 0; v < G.V(); v++) {
if (dfs.marked[v]) {
list.add(v);
}
}
return (Iterable<Integer>) list;
}
public Iterable<Integer> PathTo(int v) {
if (!hasPathTo(v)) {
return null;
}
Stack<Integer> path = new Stack<Integer>();
for (int x = v; x != s; x = edgeTo[x]) {
path.push(x);
}
path.push(s);
return path;
}
public Iterable<Integer> PathTo(Graph G,int s,int v){
DFS dfspath=new DFS(G, s);
return dfspath.PathTo(v);
}
}
关于Iterable作为返回类型的博文: https://blog.51cto.com/jition/2509344
queue不用add()用offer()的原因https://blog.csdn.net/meism5/article/details/89883976
同理:
Queue 中 remove() 和 poll()都是用来从队列头部删除一个元素。
在队列元素为空的情况下,remove() 方法会抛出NoSuchElementException异常,poll() 方法只会返回 null 。
/*
* @Description:
* @Author: YPY
* @Date: 2021-11-24 10:53:54
* @LastEditTime: 2021-11-24 11:09:53
* @LastEditors: YPY
* @Reference:
*/
package com.ypy.suanfa;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class BreadFirstSearch {
private boolean[] marked;
private int s;
private int[] edgeTo;
public void BreadFirstSearch(Graph G, int s) {
this.s = s;
this.marked = new boolean[G.V()];
this.edgeTo = new int[G.V()];
bfs(G, s);
}
public void bfs(Graph G, int s) {
Queue<Integer> queue = new LinkedList<>();
// s访问过的标记
marked[s] = true;
queue.offer(s);
if (!queue.isEmpty()) {
int v = queue.poll();
for (int w : G.adj(v)) {
if (!marked[w]) {
edgeTo[w] = v;
marked[w] = true;
queue.offer(w);
}
}
}
}
public boolean hasPathTo(int v) {
return marked[v];
}
public Iterable<Integer> pathTo(int v) {
if (!hasPathTo(v)) {
return null;
}
Stack<Integer> path = new Stack<>();
for (int i = v; i != s; i = edgeTo[i]) {
path.push(i);
}
path.push(s);
return path;
}
}