7

From Wikipedia: O(|E| + |V| log|V|)

From Big O Cheat List: O((|V| + |E|) log |V|)

I consider there is a difference between E + V log V and (E+V) log V, isn't there?

Because, if Wikipedia's one is correct, shouldn't it be shown as O(|V| log |V|) only then (Removing |E|) for a reason I do not understand?)?

What is the Big O of Dijkstra with Fibonacci-Heap?

Frank Schmitt
  • 30,195
  • 12
  • 73
  • 107
Nikola
  • 2,093
  • 3
  • 22
  • 43

2 Answers2

23

The complexity of Dijkstra's shortest path algorithm is:

    O(|E| |decrease-key(Q)| + |V| |extract-min(Q)|)

where Q is the min-priority queue ordering vertices by their current distance estimate.

For both a Fibonacci heap and a binary heap, the complexity of the extract-min operation on this queue is O(log |V|). This explains the common |V| log |V| part in the sum. For a queue implemented with an unsorted array, the extract-min operation would have a complexity of O(|V|) (the whole queue has to be traversed) and this part of the sum would be O(|V|^2).

In the remaining part of the sum (the one with the edge factor |E|), the O(1) v.s. O(log |V|) difference comes precisely from using respectively a Fibonacci heap as opposed to a binary heap. The decrease key operation which may happen for every edge has exactly this complexity. So the remaining part of the sum eventually has complexity O(|E|) for a Fibonacci heap and O(|E| log |V|) for a binary heap. For a queue implemented with an unsorted array, the decrease-key operation would have a constant-time complexity (the queue directly stores the keys indexed by the vertices) and this part of the sum would thus be O(|E|), which is also O(|V|^2).

To summarize:

  • Fibonacci heap: O(|E| + |V| log |V|)
  • binary heap: O((|E| + |V|) log |V|)
  • unsorted array: O(|V|^2)

Since, in the general case |E| = O(|V|^2), these can't be simplified further without making further assumptions on the kind of graphs dealt with.

user3146587
  • 4,250
  • 1
  • 16
  • 25
  • Ok, I think I have understood it. Just to make things clear for me: Because (talking about the `decrease-key(Q)`) Fibonacci-heap is `O(1)` then we have `O(E + V log V)` and binary-heap is `O(log V)` so we have `O((E+V) log V) = O(E log V + V log V)`. If that is correct, can't I say that Fibonacci-heap is just `O(V log V)` as `E` is actually `O(1)`? – Nikola Jan 12 '14 at 17:52
  • @Nikola |E| is not O(1). In general |E| = O(|V|^2), so you just can't simplify `O(E + V log V)` to `O(V log V)` (unless you make some additional assumptions on the kind of graphs you're dealing with). – user3146587 Jan 12 '14 at 19:53
  • But didn't you say exactly that? `In the remaining part of the sum, the O(1) v.s. O(log(|V|)) difference`? On the Dijkstra unsorted array the `O(E + V^2)` is simplified to `O(V^2)`, isn't `E` the same case here? – Nikola Jan 12 '14 at 20:04
  • @Nikola Sorry this wasn't clear: a single `|decrease-key(Q)|` operation is `O(1)` with a Fibonacci heap and `O(log(|V|))` with a binary heap. Total there are `O(|E|)` decrease-key operations. With an unsorted array, `decrease-key(Q)` is `O(1)`, but there are still `O(|E|)` decrease-key operations. Still with an unsorted array, `extract-min(Q)` is `O(|V|)`. Hence the `O(|E| + |V|^2)` complexity for Dijkstra's algorithm with an unsorted array. However, as I wrote previously, `|E|` is `O(|V|^2)`, so this can be simplified further to just `O(|V|^2)`. – user3146587 Jan 12 '14 at 20:11
  • Thank you very much for the detailed explanations! If it is no problem for you, can you also explain to me (or give me a source, because I haven't been able to find where to read on that) about the "In general `|E| = O(|V|^2)`" I cannot explain it to myself at the moment. Also, for the unsorted array, when it is `O(|E| + |V|^2)` and `|E|` is also `|V|^2` it gets `O(2|V|^2|)`, but because we don't care for the constants, that is why we remove it? And last question - if `|E| = O(|V|^2)` shouldn't we write that instead of `|E|`? – Nikola Jan 12 '14 at 20:22
  • @Nikola Why `|E| = O(|V|^2)`? How many edges in the worst-case can you have in a graph with `|V|` vertices? Just link each vertex to every other vertex. So each of the |V| vertex is linked to |V| - 1 other vertices and you don't want to count twice the edges so in this worst case scenarion |E| = |V| (|V| - 1) / 2 = O(|V|^2). – user3146587 Jan 12 '14 at 20:28
  • @Nikola Yes, O(2|V|^2) = O(|V|^2). Constants are usually discarded since they don't impact the asymptotic complexity. – user3146587 Jan 12 '14 at 20:30
  • @Nikola Why not always write `O(|V|^2)` instead of `O(|E|)`? You may want to know which parts of your formula depend on the number of edges if you're not dealing with worst-case graphs. It makes sense to replace `O(|E|)` with `O(|V|^2)` when another term in the complexity is hiding this substitution (has similar or higher complexity than `O(|V|^2)`): for instance, in the complexity for the unsorted array case. – user3146587 Jan 12 '14 at 20:35
  • Now it is as clear as it could be. Thank you very much for your time, I really appreciate those explanations and they (will) helped me a lot. – Nikola Jan 12 '14 at 20:39
  • Returning to the topic: `|E|` I understood to be the total edges of the graph. In the worst case I see it it `|E|=O(|V|^2)`. However, what about rectangular grids? It is usually said that Dijkstra is `O=(|V| log|V|) for these grids and therefore I assume that `|E|` can be "deleted", but why? – Javi Apr 09 '14 at 14:29
  • 1
    @JaviV For rectangular grids `|E|=O(|V|)` (for instance, a N x M grid with |V| = N M vertices has |E| = N (M - 1) + M (N - 1) = O(N M) = O(|V|) edges). Consequently on such a grid, Dijkstra with a Fibonacci heap is `O(|V| + |V| log |V|) = O(|V| log |V|)` and Dijkstra with a binary heap is `O((|V| + |V|) log |V|) = O(|V| log |V|)`. In both cases, `|E|` "disappears" (either being dominated by another term or because it does not add anything). – user3146587 Apr 09 '14 at 22:27
  • Wow exactly the answer I was looking for. Thank you so much! I was missing the |E| = N (M - 1) + M (N - 1) formula, I was not able to get it. By the way, is that formula for 8-connectivity of 4-connectivity? – Javi Apr 10 '14 at 08:43
0

Dijkstra's is O(|E| + |V| log|V|) with Fibonacci heap and O((|V| + |E|) log |V|) without it.

Both correct in some way. Big O Cheat List showing the most common implementation and Wiki the best there is.

O(|E| + |V| log|V|) isn't in O(|V| log|V|) btw. E is in O(|V|^2), not O(|V| log|V|).

Roam
  • 4,831
  • 9
  • 43
  • 72