深度优先搜索
目的:解决是否能从图上一点到另一点的问题
注:Bag是基础数据结构背包的实现类,附在文章的最后
图的数据结构应该能初始化一个有V个顶点的图,获得顶点和边的个数,添加边,返回与某个点相连的点的集合
图的建立API
private int V;//顶点的数目 private int E;//边的数目 private Bag<Integer>[] adj;//邻接表 //构造一个包含v个顶点的图 public GraphbyMe(int v) { this.V = v; this.E = 0; adj = new Bag[V]; //实例化数组和实例化数组里的每个对象 for (int i = 0; i < v; i++) { adj[i] = new Bag<>(); } } //获得顶点个数 public int getV() //获得边得个数 public int getE() //添加一条从v到w的边 public void addE(int v,int w) //获得邻接表 public Iterable<Integer> getAdj(int v) //图的字符串表示 @Override public String toString()
图的实现
public class GraphbyMe { private int V;//顶点的数目 private int E;//边的数目 private Bag<Integer>[] adj;//邻接表 public GraphbyMe(int v) { this.V = v; this.E = 0; adj = new Bag[v]; for (int i = 0; i < v; i++) { adj[i] = new Bag<>(); } } public int getV(){ return V; } public int getE(){ return E; } //添加一条从v到w的边 public void addE(int v,int w){ adj[v].add(w); adj[w].add(v); E++; } //获得邻接表 public Iterable<Integer> getAdj(int v){ return adj[v]; } //图的字符串表示 @Override public String toString() { String s = "共有"+V+"个顶点,"+E+"条边\n"; for (Bag<Integer> v : adj) { s+=v+":"; for (Integer e : v) { s+=e+" "; } s+="\n"; } return s; } }
深度优先搜索
private boolean[] marked;//是否有到这个点的路径 private int[] edgeTo; //记录到达这个点的上一个点 private final int s; //图的起点 //构造器,初始化对象并执行深度优先搜索 public DFSbyMe(GraphbyMe g,int s){ this.s = s; marked = new boolean[g.getV()]; edgeTo = new int[g.getV()]; dfs(g,s); } //深度优先搜索算法 private void dfs(GraphbyMe g, int v) //判断是否有到这个点的道路 public boolean hasPathTo(int w) //使用栈找出从起点到w点的道路 public Iterable<Integer> path(int w)
深度优先搜索的实现
public class DFSbyMe { private boolean[] marked;//是否有到这个点的路径 private int[] edgeTo; //记录到达这个点的上一个点 private final int s; //图的起点 //构造器,初始化对象并执行深度优先搜索 public DFSbyMe(GraphbyMe g,int s){ this.s = s; marked = new boolean[g.getV()]; edgeTo = new int[g.getV()]; dfs(g,s); } //深度优先搜索算法,遍历每个点及与这个点相连的所有顶点 private void dfs(GraphbyMe g, int v){ marked[v] = true; for (Integer w : g.getAdj(v)) { if (!marked[w]){ edgeTo[w] = v; dfs(g, w); } } } //判断是否有从顶点到这个点的道路 public boolean hasPathTo(int w){ return marked[w]; } //使用栈找出从起点到w点的道路 public Iterable<Integer> path(int w){ if (!hasPathTo(w)) return null; Stack<Integer> stack = new Stack<>(); //找到到达这个点的上一个顶点,找到后就把该点放入栈 for (int i = w; i != s ; i=edgeTo[i]) { stack.push(i); } stack.push(s); return stack; } }
测试
public class TestSearch { public static void main(String[] args) { GraphbyMe g = new GraphbyMe(9); g.addE(0,1); g.addE(5,4); g.addE(0,2); g.addE(2,4); g.addE(2,5); DFSbyMe dfSbyMe = new DFSbyMe(g,0); System.out.println(dfSbyMe.path(4)); } }
运行结果:[4, 5, 2, 0]
Bag的实现
public class Bag<Item> implements Iterable<Item> { private Bag.Node<Item> first = null; private int n = 0; public Bag() { } public boolean isEmpty() { return this.first == null; } public int size() { return this.n; } public void add(Item item) { Bag.Node<Item> oldfirst = this.first; this.first = new Bag.Node(); this.first.item = item; this.first.next = oldfirst; ++this.n; } public Iterator<Item> iterator() { return new Bag.ListIterator(this.first); } public static void main(String[] args) { Bag bag = new Bag(); while(!StdIn.isEmpty()) { String item = StdIn.readString(); bag.add(item); } StdOut.println("size of bag = " + bag.size()); Iterator var4 = bag.iterator(); while(var4.hasNext()) { String s = (String)var4.next(); StdOut.println(s); } } private class ListIterator implements Iterator<Item> { private Bag.Node<Item> current; public ListIterator(Bag.Node<Item> first) { this.current = first; } public boolean hasNext() { return this.current != null; } public void remove() { throw new UnsupportedOperationException(); } public Item next() { if (!this.hasNext()) { throw new NoSuchElementException(); } else { Item item = this.current.item; this.current = this.current.next; return item; } } } private static class Node<Item> { private Item item; private Bag.Node<Item> next; private Node() { } } }