Graph search-BFS and DFS

A graph is an important data structure. Many graph algorithms will first search to obtain the structure of the graph or the information stored by the nodes in the graph. The search technique of the graph is the core of the graph related algorithm.

The search algorithm of the graph has two design cores, namely BFS (breadth first search) and DFS (depth first search), which represent breadth first search and depth first search.

1. BFS search algorithm The
so-called breadth-first algorithm is to systematically explore the edges of the graph G with nodes as the unit to find all other nodes that can be reached from the source node. The characteristic of the breadth-first algorithm is that the search position is reached every time A point, it will continue to explore all the edges of this point that connect to other points (except the edges that reach this point from the previous point). On the whole, it starts from a source point of the graph and progresses in a certain direction. Search method. The core of the design of the BFS algorithm is the use of the data structure of the queue. What we store in the queue is the search order, and the head of the queue is the node where the current search position is located.

class Solution {
    
    
        public void search(List<List<Integer>>map) {
    
    
            /*
            * 形参二维数组map表示图,数组的一维表示图的结点,二维表示结点的边所
            * 连接的另一个结点。
            
            * 队列BFS表示搜索顺序。
            
            * searchPos用来存储每一个结点的状态(是否被搜索过),
            * false表示未被搜索,true表示以被搜索。
            */
            Queue<Integer>BFS=new LinkedList<>();
            boolean[]searchPos=new boolean[map.size()];
           
            for(int i=0;i<map.size();i++){
    
    
                //往BFS队列中插入源结点
               if(searchPos[i]==false) {
    
    
                   BFS.add(i);
                   searchPos[i]=true;
               }
               //若队列非空,则一直往下搜索
               while(!BFS.isEmpty()){
    
    
                   int thisPos=BFS.poll();
                   //判断当前搜索位置的边连接的结点是否被搜索过,若没有,则送入队列尾
                   for(int k=0;k<map.get(thisPos).size();k++){
    
    
                       if(searchPos[map.get(thisPos).get(k)]==false){
    
    
                           BFS.add(map.get(thisPos).get(k));
                           searchPos[map.get(thisPos).get(k)]=true;
                       }
                   }
               }
           }
        }
    }



2. DFS search algorithm
depth-first algorithm, take a certain point of the graph G as the source point, as long as possible, go deep in the graph as much as possible, if you can’t go deeper, go back to the previous node and find another way. After all the selections are completed, go back to the previous node, find another way, and proceed like this until you know that all the nodes in the picture have been searched. On the whole, it is-go deep -> go back, find another way -> Go deeper -> Go back, find another way -> Go deeper... The core of the design of the DFS algorithm is the use of function recursion, using recursive functions to achieve the purpose of backtracking.

class Solution {
    
    
        boolean[] searchPos;
        public void search(List<List<Integer>>map) {
    
    
            /*
             * 形参二维数组map表示图,数组的一维表示图的结点,二维表示结点的边所
             * 连接的另一个结点。

             * searchPos用来存储每一个结点的状态(是否被搜索过),
             * false表示未被搜索,true表示已被搜索。
             */
            searchPos = new boolean[map.size()];
            for(int i=0;i<map.size();i++){
    
    

                //i表示源结点,DFS算法中,任何结点都可以作为源结点
                DFS(i,map);
            }
        }
        //利用递归进行深入搜索
        private void DFS(int thisPos,List<List<Integer>>map){
    
    
            for(int i=0;i<map.get(thisPos).size();i++){
    
    
                if(searchPos[map.get(thisPos).get(i)]==false) {
    
    
                    DFS(map.get(thisPos).get(i), map);
                    searchPos[map.get(thisPos).get(i)]=true;
                }
            }
        }
    }

----------------------------------------split line-------- ------------------------------------
In fact, it is not necessary to use recursion for the DFS algorithm (myself actually I don’t like recursion. Recursive algorithms always give people a sense of insecurity.) Recently, I learned a new way to design DFS algorithm-using stack + hash table. I had always thought that using stacks can only implement binary trees. DFS traversal, but it is also possible to use the stack to implement the DFS of the graph, but it needs the assistance of a hash table.

Specific method: The stack saves the current search node. Each time a node is searched, the node is pushed into the stack, but when moving from the current search node to the next node, the current node has two processing methods: 1. Other nodes connected to the current node (there may be more than one) have not been searched, do not pop the stack; 2. Other nodes connected to the current node have searched, and pop the stack. So how to judge that the other nodes connected to the current node have been searched, this requires the use of a hash table. The specific use is to use the hash table to store the number of connected nodes that each node has searched. If it is greater than The number of all connected nodes of this node will pop the stack, otherwise the stack will not be popped when the node is searched.

The specific code is shown as an algorithm question:
Title: Give you a reference to a node in an undirected connected graph, please return a deep copy (clone) of the graph.

Problem solving idea: This problem requires us to completely copy a graph structure (different from the storage space of the original graph structure). Copying this graph is actually to search all the nodes of this graph, and copy it during the search process.

class Node {
    
    
    public int val;
    //neighbors用于存储该结点所通向的另一个结点
    public List<Node> neighbors;

    public Node() {
    
    
        val = 0;
        neighbors = new ArrayList<Node>();
    }

    public Node(int _val) {
    
    
        val = _val;
        neighbors = new ArrayList<Node>();
    }

    public Node(int _val, ArrayList<Node> _neighbors) {
    
    
        val = _val;
        neighbors = _neighbors;
    }
}

//DFS非递归算法
class Solution {
    
    
    
    public Node cloneGraph(Node node) {
    
    
        /*
        * DFS:DFS算法中所用到的栈
        * Search:记录结点的状态(是否被搜索过)
        * Val_Node:通过val映射新结点
        * Node_Neighbor:通过新结点映射neighbors
        */
        if(node==null)
            return null;
        Stack<Node>DFS=new Stack<>();
        HashSet<Node>Search=new HashSet<>();
        HashMap<Integer,Node>Val_Node=new HashMap<>();
        HashMap<Node,Integer>Node_Neighbor=new HashMap<>();

        DFS.push(node);
        Search.add(node);
        Val_Node.put(node.val,new Node(node.val));
        Node_Neighbor.put(Val_Node.get(node.val),0);
        while(!DFS.isEmpty()){
    
    
            Node peek= DFS.peek();
            Node newNode=Val_Node.get(peek.val);
            int neighbor=Node_Neighbor.get(newNode);
            Node_Neighbor.put(newNode,neighbor+1);
            if(neighbor>= peek.neighbors.size()){
    
    
                DFS.pop();
                continue;
            }
            if(!Val_Node.containsKey(peek.neighbors.get(neighbor).val)){
    
    
                int key=peek.neighbors.get(neighbor).val;
                Val_Node.put(key,new Node(key));
                Node_Neighbor.put(Val_Node.get(key),0);
            }
            if(!Search.contains(peek.neighbors.get(neighbor))){
    
    
                Search.add(peek.neighbors.get(neighbor));
                DFS.push(peek.neighbors.get(neighbor));
            }
            newNode.neighbors.add(Val_Node.get(peek.neighbors.get(neighbor).val));
        }
        return Val_Node.get(node.val);
    }

}

Guess you like

Origin blog.csdn.net/CY2333333/article/details/107798362