1. Two algorithms for graphs
This chapter inherits some specific instructions or information from the previous chapter, which can be found in the previous chapter.
1. Depth-first traversal
Before we talk about depth-first traversal, let's talk about how to walk the maze.
To explore all the passages in the maze, we need to do the following,
1): Choose an unmarked passage and lay a rope on the way you walk;
2): Mark all the intersections and passages you pass through for the first time;
3): When coming to a marked intersection (intersection with rope), go back to the previous intersection
4): Continue to go back when there is no other way to go to the intersection.
This way the ropes ensure you always find a way out, and the markings ensure you don't go through a passage twice at the same time
code show as below
package com.lxy.datastructure.graph; public class DepthFirstSearch { private boolean[] marked;//Whether it has been visited private int count;//The vertex connected with s public DepthFirstSearch(Graph g,int s) { marked=new boolean[g.getV()]; dfs(g,s); } private void dfs(Graph g,int 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 count(){ return count; } }
2, breadth-first traversal
1, take the next vertex v in the queue and mark it
2. Add all unmarked vertices adjacent to v;
Repeat the above steps
code show as below
package com.lxy.datastructure.graph; import com.lxy.datastructure.queue.Queue; import com.lxy.datastructure.stack.Stack; public class BreadthFirstPaths { private boolean[] marked;//Access mark private int[] edgeTo;// private int s;//Starting point public BreadthFirstPaths(Graph g,int s){ this.s=s; marked=new boolean[g.getV()]; edgeTo=new int[g.getV()]; bfs(g,s); } private void bfs(Graph g,int v){ Queue<Integer> queue=new Queue<Integer>(); marked[v]=true; queue.push(v); while(!queue.isEmpty()){ int h=queue.pop(); for(int w:g.adj(h)){ if(!marked(w)){ queue.push(w); marked[w]=true; edgeTo [w] = h; } } } } public boolean marked(int v){ return marked[v]; } public boolean hasPathTo(int v){ return marked[v]; } 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; } }
test case
package com.lxy.datastructure.graph; import java.io.File; import java.util.Arrays; import java.util.Iterator; import org.junit.Before; import org.junit.Test; import com.lxy.datastructure.queue.Queue; import edu.princeton.cs.introcs.In; import edu.princeton.cs.introcs.StdOut; public class GraphTest { String basePath=System.getProperty("user.dir"); File file1=null; File file2=null; Graph g1 =null; @Before public void setup(){ file1=new File(basePath,"data/graph/mediumG.txt"); file2=new File(basePath,"data/graph/tinyG.txt"); In in = new In(file2); g1=new Graph(in); } @Test public void testPrintGraph(){ System.out.println(g1.toString()); } /** * Depth-first traversal */ @Test public void depthFirstPath(){ int s =0; DeptFirstPaths path=new DeptFirstPaths(g1, s); for (int v = 0; v < g1.getV(); v++) { if (path.hasPathTo(v)) { StdOut.printf("%d to %d: ", s, v); for (int x : path.pathTo(v)) { if (x == s) StdOut.print(x); else StdOut.print("-" + x); } StdOut.println(); } else { StdOut.printf("%d to %d: not connected\n", s, v); } } System.out.println(Arrays.toString(path.getEdgeTo())); for(Iterator<Integer> it=path.pathTo(6).iterator();it.hasNext();){ System.out.println(it.next()); } } /** * Breadth-first traversal */ @Test public void testBreadthFirstPath(){ int s =0; BreadthFirstPaths path=new BreadthFirstPaths(g1, s); for (int v = 0; v < g1.getV(); v++) { if (path.hasPathTo(v)) { StdOut.printf("%d to %d: ", s, v); for (int x : path.pathTo(v)) { if (x == s) StdOut.print(x); else StdOut.print("-" + x); } StdOut.println(); } else { StdOut.printf("%d to %d: not connected\n", s, v); } } } }
output result
Breadth-first traversal output 0 to 0: 0 0 to 1: 0-1 0 to 2: 0-2 0 to 3: 0-5-3 0 to 4: 0-5-4 0 to 5: 0-5 0 to 6: 0-6 0 to 7: not connected 0 to 8: not connected 0 to 9: not connected 0 to 10: not connected 0 to 11: not connected 0 to 12: not connected Depth-first traversal output results 0 to 0: 0 0 to 1: 0-1 0 to 2: 0-2 0 to 3: 0-5-4-3 0 to 4: 0-5-4 0 to 5: 0-5 0 to 6: 0-5-4-6 0 to 7: not connected 0 to 8: not connected 0 to 9: not connected 0 to 10: not connected 0 to 11: not connected 0 to 12: not connected