¿Por qué decir que la búsqueda de amplitud se ejecuta en el tiempo

9

A menudo se dice (por ejemplo, en Wikipedia ) que el tiempo de ejecución de la búsqueda de amplitud primero (BFS) en un gráfico G=(V,E) es O(|V|+|E|) . Sin embargo, cualquier gráfico conectado tiene |V||E|+1 e, incluso en un gráfico no conectado, BFS nunca mirará un vértice fuera del componente que contiene el vértice de inicio. Ese componente contiene como máximo |E| bordes, por lo que contiene como máximo |E|+1 vértices, y esos son los únicos que visitará el algoritmo.

Esto significa que |V|+|E|2|E|+1 , entonces ¿por qué no decimos que el tiempo de ejecución es solo O(|E|) ?

Esto surgió en los comentarios sobre una pregunta sobre el tiempo de ejecución del algoritmo de Disjkstra .

David Richerby
fuente
¿Por qué supones que hay un vértice inicial? BFS en el problema de coincidencia máxima, por ejemplo, comienza desde todos los vértices no coincidentes en el algoritmo hopcroft karp. En este caso, si el gráfico dado es un bosque de muchos componentes conectados tendremos más vértices que bordes y los visitaremos todos
narek Bojikian
2
@narekBojikian Si bien BFS se puede usar de varias maneras, cuando se presenta como un algoritmo independiente, casi siempre tiene un vértice de inicio.
David Richerby

Respuestas:

9

BFS generalmente se describe de manera similar a lo siguiente (de Wikipedia ).

 1  procedure BFS(G,start_v):
 2      let Q be a queue
 3      label start_v as discovered
 4      Q.enqueue(start_v)
 5      while Q is not empty
 6          v = Q.dequeue()
 7          if v is the goal:
 8              return v
 9          for all edges from v to w in G.adjacentEdges(v) do
10             if w is not labeled as discovered:
11                 label w as discovered
12                 w.parent = v
13                 Q.enqueue(w)

El problema es algo sutil: ¡se esconde en la línea 3! La pregunta es, ¿qué estructura de datos vamos a utilizar para almacenar qué vértices se han descubierto?

falseΘ(|V|)|V||E|O(|V|+|E|)

Θ(|V|)O(|V||E|)O(|E|2)|V|4|V||E||V|3

O(log|V|)O(|E|log|V|)

c|E|+1c+2c+4c++2|E|4|E| O(1)O(|E|)

O(|E|)4|E|O(|E|)O(|V|+|E|)

David Richerby
fuente
1
Creo que podría ser demasiado fuerte afirmar que las tablas hash en la práctica tienen un rendimiento de caché deficiente. Si se implementa con encadenamiento (es decir, listas vinculadas), estoy de acuerdo. Pero si se implementa con una porción continua de memoria y direccionamiento abierto, no tanto.
Juho
Maravillosa respuesta de hecho! Sin embargo, una nota marginal es que las tablas hash de tamaño dinámico son una buena opción no solo si hay muchos componentes pequeños, sino también si el valor hash de cualquier vértice está limitado por una constante razonable y esto sucede a menudo. Buena respuesta!
Carlos Linares López
1
David, tuve pensamientos similares hace años. Creo que la respuesta radica en las perspectivas históricas.
kelalaka