Depth-first traversal (DFS) and breadth-first traversal (BFS) of JS algorithm

Posted by pontiac007 on Tue, 14 May 2019 21:53:03 +0200

background

When developing a page, we sometimes encounter the need to traverse a dom node in the page to find the target dom node. Our normal practice is to use the selector document. getElementsById (), document.getElementsByName() or document.getElementsByTagName(), but in this article, we look for the dom node from an algorithmic point of view, while understanding depth first. The principle of traversal (DFS) and breadth first traversal (BFS).

Get ready

Suppose the dom structure on the page is as follows:

<div id="root">
    <ul>
        <li>
            <a href="">
                <img src="" alt="">
            </a>
        </li>
        <li>
            <span></span>
        </li>
        <li>
        </li>
    </ul>
    <p></p>
    <button></button>
</div>

Let's turn this dom structure into a tree


After that, the dom structure seems to be much clearer.

Depth-First Search

This method traverses the dom tree in a vertical dimension, starting from a dom node and traversing its children until all its children have been traversed and then traversing its siblings. That is to say, as shown in the figure (the traversal order is red-letter lock label):


js implements the algorithm code (recursive version):

function deepFirstSearch(node,nodeList) {  
    if (node) {    
        nodeList.push(node);    
        var children = node.children;    
        for (var i = 0; i < children.length; i++) 
        //Each recursion passes down the traversed nodes and the array stored by the nodes
        deepFirstSearch(children[i],nodeList);    
    }    
    return nodeList;  
} 

Non-recursive version:

function deepFirstSearch(node) {
    var nodes = [];
    if (node != null) {
        var stack = [];
        stack.push(node);
        while (stack.length != 0) {
        var item = stack.pop();
        nodes.push(item);
        var children = item.children;
        for (var i = children.length - 1; i >= 0; i--)
            stack.push(children[i]);
        }
    }
    return nodes;
}

DepFirstSearch accepts two parameters. The first parameter is the node that needs to be traversed. The second parameter is the array stored by the node and returns the array after traversal. The element order of the array is the traversal order.

let root = document.getElementById('root')
deepTraversal(root,nodeList=[])

Console output

breadth-first traverse

This method traverses the dom tree in a horizontal dimension. Starting from the first sub-node of the node, it traverses all the sibling nodes of the node, then traverses the sub-nodes of the first node. After the traversal, it does not go deep for the time being and begins to traverse the sub-nodes of the sibling node. That is to say, as shown in the figure (the traversal order is red-letter lock label):


js implementation algorithm code (recursive version):

function breadthFirstSearch(node) {
    var nodes = [];
    var i = 0;
    if (!(node == null)) {
        nodes.push(node);
        breadthFirstSearch(node.nextElementSibling);
        node = nodes[i++];
        breadthFirstSearch(node.firstElementChild);
    }
    return nodes;
}

The recursive version of BFS will cause stack overflow because of its deep hierarchy: Maximum call stack size exceeded, but the order of traversal is still no problem. It can be operated during traversal without returning the traversal array.
Non-recursive version:

function breadthFirstSearch(node) {  
    var nodes = [];  
    if (node != null) {  
        var queue = [];  
        queue.unshift(node);  
        while (queue.length != 0) {  
            var item = queue.shift();  
            nodes.push(item);  
            var children = item.children;  
            for (var i = 0; i < children.length; i++)  
                queue.push(children[i]);  
        }  
    }  
    return nodes;  
}

Console output results:

summary

BFS and DFS are both algorithms of graphs. The version described in this paper is relatively simple. For undirected and disconnected graphs, more algorithms based on JavaScript will be updated in the future.

Topics: Javascript