¿Cuál es el significado de usar una cola prioritaria en el algoritmo de Dijkstra? ¿Qué diferencia hay si usamos una cola normal?

Supongo que ha estudiado el algoritmo de Dijkstra y cómo se implementan las colas de prioridad mínima, por ejemplo, utilizando un montón dinámico binario. Para obtener descripciones de montones binarios, puede consultar un buen libro de texto o buscar en Internet.

Este PDF (Página en princeton.edu) tiene buenas explicaciones (con ilustraciones gráficas) de cómo funcionan los montones binarios (y otras variantes más sofisticadas). Lo encontré buscando en Google. Puede encontrar referencias aún mejores en Internet.

En el algoritmo de Dijkstra, el paso importante es seleccionar un vértice inexplorado v de manera que haya un borde (u, v) en el gráfico, donde u es un vértice ya explorado, y d ‘(v) = dist (u) + costo ( u, v) es mínimo. Aquí, dist (u) es la longitud de la ruta más corta ya encontrada desde el vértice fuente s hasta el vértice u , y el costo (u, v) es el peso del borde de u a v .

Si almacenamos los vértices inexplorados en una matriz simple / lista vinculada, tendríamos que iterar sobre toda la lista cada vez para encontrar el vértice deseado v, con un mínimo de d ‘(v) ( d’ (v) = dist (u) + costo (u, v) ).

Si almacenamos los vértices en una cola de prioridad con d ‘(v) como clave para cada vértice, podemos obtener el vértice con un mínimo de d’ (v) mediante la operación Extract-Min . Si usamos un montón binario (min-), la complejidad asintótica de la operación Extract-Min será O (log n) .

Después de seleccionar el vértice v y actualizar dist (v) , podemos encontrar que tenemos una ruta más corta a otro vértice inexplorado w a v , es decir, una ruta con costo d ‘(w) = dist (v) + costo (v, w ) , que es menor que el costo de la ruta existente a w .

Este vértice estará en la cola de prioridad, y su valor clave deberá cambiarse al nuevo valor utilizando la operación Decrease-Key , que disminuirá la clave de un determinado elemento y lo burbujeará si es necesario para garantizar el mínimo propiedad del montón. Un montón binario (min) apoyará la operación de Decrease-Key con complejidad O (log n) .

Nuevamente, si hubiéramos usado una lista simple, este paso nos habría requerido iterar sobre la lista completa para actualizar la clave de un vértice.

Además, existen otras estructuras de datos que se pueden usar para implementar una cola prioritaria de manera más eficiente, como los montones binomiales y los montones de Fibonacci. Pero estos vienen a expensas de la complejidad añadida.

La cola de prioridad selecciona el siguiente vértice para asegurar (eventualmente) las rutas más cortas en un gráfico ponderado. Si usa una cola FIFO en su lugar, no podrá contabilizar pesos de borde arbitrarios. Esto será esencialmente una búsqueda de amplitud que solo garantiza encontrar las rutas más cortas en gráficos no ponderados. El uso de una cola prioritaria tiene el costo de un mayor tiempo de ejecución, generalmente por un factor de registro.

Si bien utilizar una cola de prioridad en el algoritmo de Dijkstra tiene sentido para gráficos dispersos, puede escapar sin un contenedor explícito para gráficos densos (sin una desaceleración).

Si su gráfico tiene pesos de bordes enteros pequeños (como 2, 3, 4), puede reducir el problema de la ruta más corta a uno en un gráfico no ponderado con más bordes: divida los bordes del peso 2 en un par de bordes no ponderados, y así en.

Por supuesto, puede hacerlo sin una cola prioritaria, pero no sé por qué elegiría hacerlo. Las colas de prioridad son una opción muy natural y obvia para implementar los algoritmos de Prim y Dijkstra, que son casi lo mismo.

En cada paso, desea tomar el límite de peso mínimo de cada uno de los nodos que ha alcanzado en el paso anterior. Una cola prioritaria hace exactamente esto, por lo que solo tiene que poner todos los nodos que se pueden visitar en uno.

Realmente no veo por qué no querrías usar un PQ. Si le parece demasiado complicado, realmente necesita volver a las estructuras de datos y aprender un montón.

Cuando estaba leyendo el algoritmo de Dijkstra para mi libro HPC (Introducción a la computación científica de alto rendimiento) me preguntaba sobre lo mismo. Así que escribí mi propia prueba de corrección, y descubrí que usar el valor más bajo es realmente crucial para el algoritmo.

Esta no es una prueba completa de que no puede hacerlo, pero lo anterior establece que no puede mantener la esencia del algoritmo de Dijkstra sin una cola de prioridad. Podría generar todos los caminos y elegir el más corto, pero ese es un algoritmo diferente.

En un punto del algoritmo, debe calcular el siguiente nodo para visitar. Debe seleccionar el nodo más cercano al conjunto de nodos que ya ha visitado.

Para hacer esto, debe mantener los nodos no visitados en una estructura y es mucho más eficiente si los mantiene ordenados. Puede usar una cola prioritaria o un montón, pero siempre debe tener a mano el nodo de menor costo.