vlambda博客
学习文章列表

Java:[算法]深度优先搜索DFS

package com.unit4.Graph;
import com.unit1.algs1_2.Stack;
/** * @Author Kou * @Date: 2021/4/26 15:55 * @Description: DFS */public class DepthFirstPath { private boolean[] marked; //此顶点是否已经调用了dfs(); private int[] edgeTo; //每个顶点到起点的路径。从起点到一个顶点已知的最后一条路径。 private final int s; //起点
public DepthFirstPath(Graph graph, int s) { this.marked = new boolean[graph.VERTEX_NUM()]; this.edgeTo = new int[graph.VERTEX_NUM()]; this.s = s; dfs(graph, s); }
/** * 深度优先搜索DFS * * @param graph a graph * @param v 起点 */ private void dfs(Graph graph, int v) { marked[v] = true; //调用当前结点 for (int w : graph.adj(v)) { if (!marked[w]) { //如果当前结点还没有被调用 edgeTo[w] = v; //记录最后一条已知的路径 dfs(graph, w); } } }
/** * 是否存在从s到v的路径 * * @param v 终点 * @return Yes or No */ public boolean hasPathTo(int v) { return marked[v]; }
/** * s到v的路径,如果不存在则返回null * * @param v 终点 * @return Path from s to v */ public Iterable<Integer> pathTo(int v) { if (!hasPathTo(v)) { return null; } Stack<Integer> path = new Stack<>(); for (int x = v; x != s; x = edgeTo[x]) { path.push(x); } path.push(s); return path; }}
package com.unit4.Graph;
import java.util.Scanner;
/** * 邻接表无向图 */public class Graph { private final int VERTEX_NUM; //顶点数目 private int edgeNum; //边的数目 private Bag<Integer>[] adjacencyList; //邻接表
/** * 创建一个含有VERTEX_NUM个顶点但不含有边的图 * * @param VERTEX_NUM vertex number */ public Graph(int VERTEX_NUM) { this.VERTEX_NUM = VERTEX_NUM; this.edgeNum = 0; adjacencyList = new Bag[VERTEX_NUM]; //创建邻接表 for (int v = 0; v < VERTEX_NUM; v++) { //将所有链表初始化为空 adjacencyList[v] = new Bag<>(); } }
/** * 从标准输入流中读取一幅图 * * @param in 输入 */ public Graph(Scanner in) { this(in.nextInt()); //读取VERTEX并将图初始化 int edgeNum = in.nextInt(); //读取edgeNum for (int i = 0; i < edgeNum; i++) { //添加一条边 int v = in.nextInt(); //读取两个顶点 int w = in.nextInt(); addEdge(v, w); } }
public int VERTEX_NUM() { return this.VERTEX_NUM; }
public int edgeNum() { return this.edgeNum; }
/** * add an edge * * @param v a vertex * @param w another vertex */ public void addEdge(int v, int w) { adjacencyList[v].add(w); //将w添加进v的链表中 adjacencyList[w].add(v); //将v添加进w的链表中 edgeNum++; //边的总数+1 }
/** * 与v相邻的所有顶点 * * @param v a vertex * @return all of v's neighbors */ public Iterable<Integer> adj(int v) { return adjacencyList[v]; }
/** * 计算v的度数 * * @param graph 图 * @param v v顶点 * @return 返回v的度数 */ public static int degree(Graph graph, int v) { int degree = 0; for (int w : graph.adj(v)) { degree++; } return degree; }
/** * 邻接表的字符串表示 * * @return 邻接表字符串 */ @Override public String toString() { String s = VERTEX_NUM + "vertices," + edgeNum + " edges\n"; for (int v = 0; v < VERTEX_NUM; v++) { s = s + v + ": "; for (int w : this.adj(v)) { s = s + w + " "; } s = s + "\n"; } return s; }}
package com.unit1.algs1_2;
import java.util.Iterator;
/** * 下压堆栈 (链表实现) * date 2021/3/20 * * @param <Item> * @author Kou */public class Stack<Item> implements Iterable<Item> { private Node first; // 栈顶(首元结点) private int N; // 元素数量
private class Node { //结点嵌套类 Item item; Node next; }
public boolean isEmpty() { return N == 0; }
public int size() { return N; }
public void push(Item item) { //将元素压入栈 Node oldFirst = first; first = new Node(); first.item = item; first.next = oldFirst; N++; }
public Item pop() { //出栈 Item item = first.item; first = first.next; N--; return item; }
@Override public Iterator<Item> iterator() { return new ReverseStack(); }
private class ReverseStack implements Iterator<Item> { // 支持后进先出的迭代 private Node current = first;
@Override public boolean hasNext() { return current != null; }
@Override public Item next() { Item item = (Item) current.item; current = current.next; return item; }
@Override public void remove() {
} }}
package com.unit4.Graph;
import java.util.Scanner;
/** * @Author Kou * @Date: 2021/4/26 16:31 * @Description: DFS测试用例 */public class DFSTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); Graph graph = new Graph(in); int s = in.nextInt(); DepthFirstPath dfs = new DepthFirstPath(graph, s);
for (int v = 0; v < graph.VERTEX_NUM(); v++) {
System.out.print(s + " to " + v + ": ");
if (dfs.hasPathTo(v)) { for (int x : dfs.pathTo(v)) { if (x == s) { //如果x等于起点 System.out.print(x); } else { System.out.print("-" + x); } } }
System.out.println();
} }}