Performing Breadth First Search recursively

后端 未结 21 2346
不思量自难忘°
不思量自难忘° 2020-11-28 01:12

Let\'s say you wanted to implement a breadth-first search of a binary tree recursively. How would you go about it?

Is it possible using only the call-stack

相关标签:
21条回答
  • 2020-11-28 01:56

    Here is short Scala solution:

      def bfs(nodes: List[Node]): List[Node] = {
        if (nodes.nonEmpty) {
          nodes ++ bfs(nodes.flatMap(_.children))
        } else {
          List.empty
        }
      }
    

    Idea of using return value as accumulator is well suited. Can be implemented in other languages in similar way, just make sure that your recursive function process list of nodes.

    Test code listing (using @marco test tree):

    import org.scalatest.FlatSpec
    
    import scala.collection.mutable
    
    class Node(val value: Int) {
    
      private val _children: mutable.ArrayBuffer[Node] = mutable.ArrayBuffer.empty
    
      def add(child: Node): Unit = _children += child
    
      def children = _children.toList
    
      override def toString: String = s"$value"
    }
    
    class BfsTestScala extends FlatSpec {
    
      //            1
      //          / | \
      //        2   3   4
      //      / |       | \
      //    5   6       7  8
      //  / |           | \
      // 9  10         11  12
      def tree(): Node = {
        val root = new Node(1)
        root.add(new Node(2))
        root.add(new Node(3))
        root.add(new Node(4))
        root.children(0).add(new Node(5))
        root.children(0).add(new Node(6))
        root.children(2).add(new Node(7))
        root.children(2).add(new Node(8))
        root.children(0).children(0).add(new Node(9))
        root.children(0).children(0).add(new Node(10))
        root.children(2).children(0).add(new Node(11))
        root.children(2).children(0).add(new Node(12))
        root
      }
    
      def bfs(nodes: List[Node]): List[Node] = {
        if (nodes.nonEmpty) {
          nodes ++ bfs(nodes.flatMap(_.children))
        } else {
          List.empty
        }
      }
    
      "BFS" should "work" in {
        println(bfs(List(tree())))
      }
    }
    

    Output:

    List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    
    0 讨论(0)
  • 2020-11-28 01:59

    BFS for a binary (or n-ary) tree can be done recursively without queues as follows (here in Java):

    public class BreathFirst {
    
        static class Node {
            Node(int value) {
                this(value, 0);
            }
            Node(int value, int nChildren) {
                this.value = value;
                this.children = new Node[nChildren];
            }
            int value;
            Node[] children;
        }
    
        static void breathFirst(Node root, Consumer<? super Node> printer) {
            boolean keepGoing = true;
            for (int level = 0; keepGoing; level++) {
                keepGoing = breathFirst(root, printer, level);
            }
        }
    
        static boolean breathFirst(Node node, Consumer<? super Node> printer, int depth) {
            if (depth < 0 || node == null) return false;
            if (depth == 0) {
                printer.accept(node);
                return true;
            }
            boolean any = false;
            for (final Node child : node.children) {
                any |= breathFirst(child, printer, depth - 1);
            }
            return any;
        }
    }
    

    An example traversal printing numbers 1-12 in ascending order:

    public static void main(String... args) {
        //            1
        //          / | \
        //        2   3   4
        //      / |       | \
        //    5   6       7  8
        //  / |           | \
        // 9  10         11  12
    
        Node root = new Node(1, 3);
        root.children[0] = new Node(2, 2);
        root.children[1] = new Node(3);
        root.children[2] = new Node(4, 2);
        root.children[0].children[0] = new Node(5, 2);
        root.children[0].children[1] = new Node(6);
        root.children[2].children[0] = new Node(7, 2);
        root.children[2].children[1] = new Node(8);
        root.children[0].children[0].children[0] = new Node(9);
        root.children[0].children[0].children[1] = new Node(10);
        root.children[2].children[0].children[0] = new Node(11);
        root.children[2].children[0].children[1] = new Node(12);
    
        breathFirst(root, n -> System.out.println(n.value));
    }
    
    0 讨论(0)
  • 2020-11-28 01:59

    Following is my code for completely recursive implementation of breadth-first-search of a bidirectional graph without using loop and queue.

    public class Graph { public int V; public LinkedList<Integer> adj[]; Graph(int v) { V = v; adj = new LinkedList[v]; for (int i=0; i<v; ++i) adj[i] = new LinkedList<>(); } void addEdge(int v,int w) { adj[v].add(w); adj[w].add(v); } public LinkedList<Integer> getAdjVerted(int vertex) { return adj[vertex]; } public String toString() { String s = ""; for (int i=0;i<adj.length;i++) { s = s +"\n"+i +"-->"+ adj[i] ; } return s; } } //BFS IMPLEMENTATION public static void recursiveBFS(Graph graph, int vertex,boolean visited[], boolean isAdjPrinted[]) { if (!visited[vertex]) { System.out.print(vertex +" "); visited[vertex] = true; } if(!isAdjPrinted[vertex]) { isAdjPrinted[vertex] = true; List<Integer> adjList = graph.getAdjVerted(vertex); printAdjecent(graph, adjList, visited, 0,isAdjPrinted); } } public static void recursiveBFS(Graph graph, List<Integer> vertexList, boolean visited[], int i, boolean isAdjPrinted[]) { if (i < vertexList.size()) { recursiveBFS(graph, vertexList.get(i), visited, isAdjPrinted); recursiveBFS(graph, vertexList, visited, i+1, isAdjPrinted); } } public static void printAdjecent(Graph graph, List<Integer> list, boolean visited[], int i, boolean isAdjPrinted[]) { if (i < list.size()) { if (!visited[list.get(i)]) { System.out.print(list.get(i)+" "); visited[list.get(i)] = true; } printAdjecent(graph, list, visited, i+1, isAdjPrinted); } else { recursiveBFS(graph, list, visited, 0, isAdjPrinted); } }

    0 讨论(0)
  • 2020-11-28 02:02

    Here's a Scala 2.11.4 implementation of recursive BFS. I've sacrificed tail-call optimization for brevity, but the TCOd version is very similar. See also @snv's post.

    import scala.collection.immutable.Queue
    
    object RecursiveBfs {
      def bfs[A](tree: Tree[A], target: A): Boolean = {
        bfs(Queue(tree), target)
      }
    
      private def bfs[A](forest: Queue[Tree[A]], target: A): Boolean = {
        forest.dequeueOption exists {
          case (E, tail) => bfs(tail, target)
          case (Node(value, _, _), _) if value == target => true
          case (Node(_, l, r), tail) => bfs(tail.enqueue(List(l, r)), target)
        }
      }
    
      sealed trait Tree[+A]
      case class Node[+A](data: A, left: Tree[A], right: Tree[A]) extends Tree[A]
      case object E extends Tree[Nothing]
    }
    
    0 讨论(0)
  • 2020-11-28 02:02
    #include <bits/stdc++.h>
    using namespace std;
    #define Max 1000
    
    vector <int> adj[Max];
    bool visited[Max];
    
    void bfs_recursion_utils(queue<int>& Q) {
        while(!Q.empty()) {
            int u = Q.front();
            visited[u] = true;
            cout << u << endl;
            Q.pop();
            for(int i = 0; i < (int)adj[u].size(); ++i) {
                int v = adj[u][i];
                if(!visited[v])
                    Q.push(v), visited[v] = true;
            }
            bfs_recursion_utils(Q);
        }
    }
    
    void bfs_recursion(int source, queue <int>& Q) {
        memset(visited, false, sizeof visited);
        Q.push(source);
        bfs_recursion_utils(Q);
    }
    
    int main(void) {
        queue <int> Q;
        adj[1].push_back(2);
        adj[1].push_back(3);
        adj[1].push_back(4);
    
        adj[2].push_back(5);
        adj[2].push_back(6);
    
        adj[3].push_back(7);
    
        bfs_recursion(1, Q);
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-28 02:04

    Here is a JavaScript Implementation that fakes Breadth First Traversal with Depth First recursion. I'm storing the node values at each depth inside an array, inside of a hash. If a level already exists(we have a collision), so we just push to the array at that level. You could use an array instead of a JavaScript object as well since our levels are numeric and can serve as array indices. You can return nodes, values, convert to a Linked List, or whatever you want. I'm just returning values for the sake of simplicity.

    BinarySearchTree.prototype.breadthFirstRec = function() {
    
        var levels = {};
    
        var traverse = function(current, depth) {
            if (!current) return null;
            if (!levels[depth]) levels[depth] = [current.value];
            else levels[depth].push(current.value);
            traverse(current.left, depth + 1);
            traverse(current.right, depth + 1);
        };
    
        traverse(this.root, 0);
        return levels;
    };
    
    
    var bst = new BinarySearchTree();
    bst.add(20, 22, 8, 4, 12, 10, 14, 24);
    console.log('Recursive Breadth First: ', bst.breadthFirstRec());
    /*Recursive Breadth First:  
    { '0': [ 20 ],
      '1': [ 8, 22 ],
      '2': [ 4, 12, 24 ],
      '3': [ 10, 14 ] } */
    

    Here is an example of actual Breadth First Traversal using an iterative approach.

    BinarySearchTree.prototype.breadthFirst = function() {
    
        var result = '',
            queue = [],
            current = this.root;
    
        if (!current) return null;
        queue.push(current);
    
        while (current = queue.shift()) {
            result += current.value + ' ';
            current.left && queue.push(current.left);
            current.right && queue.push(current.right);
        }
        return result;
    };
    
    console.log('Breadth First: ', bst.breadthFirst());
    //Breadth First:  20 8 22 4 12 24 10 14
    
    0 讨论(0)
提交回复
热议问题