Java implementation of depth-first algorithm

Depth First Search

As the name suggests, DFS pays more attention to the development of the " end point " than the breadth-first algorithm .

There are many implementations of this algorithm on the Internet, here is a relatively easy-to-understand Java implementation ( graph representation based on adjacency matrix )

The main idea is object-oriented modeling + recursive implementation, which builds models for graphs, nodes, and stacks respectively. List is used in this implementation . If you want to be more primitive, you can replace it with an array. The following classes throw away the code of various definitions and annotations. The actual code may only add up to seventy or eighty lines. The most important recursive logic is to execute the doSearch() method in the class, which is actually Twenty lines.

Arbitrarily initialized graph:

convert to adjacency matrix:
  0 1 2 3 4 5 6 7 8 9
0 0             1    
1   0       1 1 1 1  
2     0       1      
3       0       1    
4         0     1    
5   1       0       1
6   1 1       0      
7 1 1   1 1     0    
8   1             0  
9           1       0
For an acyclic connected graph, the number of connections is always the number of nodes n-1, and each row and column appears at least once in 1

The result output by the program is:


the value of the node labeled n is initialized to the string of No.n. Here, a node 5 is arbitrarily selected as the initial node, which can be changed at will in the program

stack class

package com.ryo.algorithm.dfs;

/**
 * Stack model required by DFS
 * @author shiin
 */
public class Stack {
	
	/**
	 * current stack
	 * The sequence of the array itself is the stack order
	 * The corresponding value is the index of the pushed element Node instance in the graph
	 */
	private int[] currentStack;
	/**
	 * maximum stack depth
	 */
	private int max_depth;
	/**
	 * current depth
	 */
	private int depth;
	
	public Stack(int max_depth) {
		this.max_depth = max_depth;
		currentStack = new int[max_depth];
		depth = -1;
	}
	
	public void push(int index) {
		if(depth > max_depth-1){
			return;
		}
		currentStack[++depth] = index;
	}
	
	public void pop() {
		if(depth < 0){
			return;
		}
		currentStack[depth--] = 0;
	}
	
	/**
	 * Get the top index value of the stack
	 * @return Node's index in the Graph instance ArrayList
	 */
	public int getTopIndex() {
		if(depth < 0) {
			return -1;
		}
		return currentStack[depth];
	}
	
	/**
	 * Get the current stack depth
	 * @return stack depth
	 */
	public int getDepth() {
		return depth;
	}
}

Node class

package com.ryo.algorithm.dfs;

/**
 * Node model
 * @author shiin
 */
public class Node {
	/**
	 * Has it been traversed
	 * true when all its child nodes and itself have been traversed
	 */
	private boolean isVisited;
	/**
	 * the value of this node
	 */
	private String value;
	
	public Node(String value) {
		isVisited = false;
		this.value = value;
	}
	
	public static Node createNode(String str) {
		return new Node(str);
	}

	public boolean isVisited() {
		return isVisited;
	}

	public void setVisited(boolean isVisited) {
		this.isVisited = isVisited;
	}

	public String getValue() {
		return value;
	}
}

graph class

package com.ryo.algorithm.dfs;

import java.util.ArrayList;

/**
 * Graph model
 * @author shiin
 */
public class Graph {
	
	/**
	 * Take the serial number of the ArrayList as the subscript
	 * There are instances of each node
	 */
	private ArrayList<Node> list;
	/**
	 * The connection situation of the figure
	 */
	private int[][] link;
	
	public Graph(ArrayList<Node> list ,int[][] link) {
		this.list = list;
		this.link = link;
	}

	
	public String getValueByIndex(int index) {	
		return this.list.get(index).getValue();
	}
	
	public int getNextInvisitedChildIndex(int index) {
		if(index == -1) {
			return -1;
		}
		int[] temp = this.link[index];
		for(int i=0 ;i<this.link.length ;i++) {
			if(temp[i] == 1) {
				if(!this.list.get(i).isVisited()) {
					return i;
				}
			}
		}
		return -1;
	}
	
	public void setVisited(int index) {
		this.list.get(index).setVisited(true);
	}
}

Execution class
package com.ryo.algorithm.dfs;

import java.util.ArrayList;
import java.util.List;

/**
 * set initial value
 * Used to test the entire DFS process
 * @author shiin
 */
public class Search {
	private static final int SIZE = 10;
	
	private Stack stack;
	private Graph graph;
	private List<String> result;

	
	public static void main(String[] args) {
		Search s = new Search();
		s.init();
		s.doSearch (5);
		for(String str : s.getResult()) {
			System.out.println(str);
		}
	}

	
	public void setLink(int[][] link ,int i ,int j) {
		link[i][j] = 1;
		link[j][i] = 1;
	}
	
	public void init() {
		//Create SIZE nodes
		ArrayList<Node> list = new ArrayList<Node>();
		for(int i=0 ;i<SIZE ;i++) {
			list.add(Node.createNode("No."+i));
		}
		//Simulate the connection situation based on the adjacency matrix notation
		int[][] link = new int[SIZE][SIZE];
		setLink(link,0, 7);
		setLink(link,1, 7);
		setLink(link,1, 8);
		setLink(link,1, 5);
		setLink(link,2, 6);
		setLink(link,3, 7);
		setLink(link,4, 7);
		setLink(link,5, 6);
		setLink(link,5, 9);
		graph = new Graph(list ,link);
		stack = new Stack(SIZE);
		result = new ArrayList<String>();
	}
	
	/**
	 * Here is the main logic method of the whole DFS
	 * You can choose any entrance
	 * @param index entry number
	 */
	public void doSearch(int index) {
		stack.push(index); //Push into the stack, the current node number is at the top of the stack
		result.add(graph.getValueByIndex(index)); //Save the value of the node
		graph.setVisited(index); //Set the node's isVisited to true
		int next = graph.getNextInvisitedChildIndex(index);//Find the subscript of the next child node according to the link[][] matrix table, if there is no unvisited child node, return -1
		if(next == -1) { // * if all children of the current node have been visited
			while(stack.getDepth() != -1) { //Whether the current stack depth is -1, the initial value of the stack depth is -1, indicating that the stack is empty
				stack.pop(); //If there are still elements in the stack, and the program runs here, it means that the current top node of the stack has no accessible child nodes. Here, pop the stack once, so that the parent node of the current node goes to the top of the stack
				int topindex = stack.getTopIndex(); //Get the parent node number
				int nextchild = graph.getNextInvisitedChildIndex(topindex);//Determine whether its parent node has unvisited child nodes
				if(nextchild == -1) { //If its parent node has no accessible child nodes, continue to loop, pop the parent node from the stack, get the grandfather node, until the stack is empty, or find a parent node that has unvisited child nodes
					continue;
				}
				else {
					doSearch(nextchild); //If an unvisited child node is found in one of its ancestor nodes, jump out of the while loop to find the child node to visit
				}
			}																	
			return; //When the while loop looking for child nodes is terminated because the stack is empty, it means that all nodes have been traversed
		} // Between * and the * sign above is the process of backtracking the parent node by looping out the stack and finding the next accessible child node
		doSearch(next); //If there are unvisited child nodes, continue recursive access according to the subscript from next
	}
	
	public List<String> getResult(){
		return this.result;
	}

}



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325659241&siteId=291194637