1

I've looked at other answers on here, but everything is either is messily written, or the code doesn't operate the same as mine does. All I am looking for is a crystal clear explanation as to why the time complexity of this breadth first search depicted below is O(v + e).

class Node {
  constructor(name) {
    this.name = name;
    this.children = [];
  }

  breadthFirstSearch() {
    const array = []
    const queue = [this]
        
        while(queue.length) {
            const node = queue.shift()
            array.push(node.name)
            queue.push(...node.children)
        }
        
        return array
  }
}

Each of the vertexes below are each of the Node class depicted above. You can imagine the breadthFirstSearch method being called by the "A" node.

           A
        /  |  \
       B   C   D
      / \     / \
     E   F   G   H
        / \
       I   J

I understand the O(v) part, because its pretty clear that we visit every node. The O(e) part is the one I cannot wrap my head around. Thanks in advance.

Dan Zuzevich
  • 3,651
  • 3
  • 26
  • 39

3 Answers3

1

Isn't e = v-1, since every vertex is connected to 1 parent except the root? If that's the case, then the e term is just to be pedantic and it could be rewritten as O(v).

If you look at the wikipedia page for Breadth-first search (https://en.wikipedia.org/wiki/Breadth-first_search), it gives the time complexity as O(|V| + |E|) for a general graph, where the number of edges |E| can be as high as |V|^2 if every pair of vertices is connected by an edge. In the worst case, BFS has to inspect every edge. A tree is a special case of a graph in which the number of edges is |V|-1.

Neal Burns
  • 839
  • 4
  • 5
1

The time complexity of running a breadth-first search on a general graph, in which there can be cycles and multiple paths between the same pair of nodes, is O(v + e). The complex arguments you're likely used to seeing are mostly there to justify the additive "+ e" term rather than the v term.

In the case of running a BFS over a tree, the runtime is O(v). There are a couple of ways to see this:

  1. Each node in the tree is touched at most twice: first when it's pushed into the queue when its parent is processed, and second when it itself is taken out of the queue and has its children processed. That means that the work done is proportional to how many nodes are in the tree, which is where the O(v) term comes from.
  2. If you ignore the cost of pushing the children into the queue, the loop clearly is going to run at most once per node in the tree, since nodes can only be enqueued at most once. That gives us an O(v) baseline amount of work, ignoring the push costs. So the part we have to work out is how much work is required to do all the pushes into the queue. Each node can be pushed at most once, so across all iterations of the outer loop the total work done pushing thing is O(v), so the total work done is O(v).
  3. If you trust that the cost of breadth-first search in a general graph with v nodes and e edges is O(v + e), then the cost of a BFS over a tree must be O(v), because in a tree we have the rule that e = v - 1. One way to see this: each node except the root has one edge entering it.
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
0

In case the graph is a tree, then O() = O(+), as in trees we have the equality = −1.

If the graph is connected and has cycles (i.e. it would have more edges than its spanning tree), then BFS is O(). This is because every edge has to be visited (even if only to realise it connects to an already visited node).

If the graph is possibly disconnected, i.e. a collection of multiple connected components, then it is possible that there are more nodes than edges, and we know that BFS will have to visit all nodes, so then O() would not cover it, and it is rather O().

To cover for all these possibilities we must say O(+) or O(max(,)), which is the same complexity. But if you are only interested in trees, you can also say either O() or O(), as then they are all equivalent.

trincot
  • 317,000
  • 35
  • 244
  • 286