【问题标题】:Dijkstra path finder in CC中的Dijkstra路径查找器
【发布时间】:2021-02-22 16:08:40
【问题描述】:

我正在学习 Dijkstra algorithm,我正在测试来自 GeeksforGeeks 的代码。我希望程序也打印 2 个节点之间最短距离的路径。

我定义了:

int parent[V]

作为一个全局变量来存储节点,这将为我提供最短路径。并且:

int end_point = 5;

设置结束节点为5。

// A C program for Dijkstra's single source shortest path algorithm. 
// The program is for adjacency matrix representation of the graph 

#include <limits.h> 
#include <stdio.h> 
#include <stdbool.h>


// Number of vertices in the graph 
#define V 9 
  
// Define shortest path array
int parent[V];
int end_node = 5;

// A utility function to find the vertex with minimum distance value, from 
// the set of vertices not yet included in shortest path tree 
int minDistance(int dist[], bool sptSet[]) 
{ 
    // Initialize min value 
    int min = INT_MAX, min_index; 
  
    for (int v = 0; v < V; v++) 
        if (sptSet[v] == false && dist[v] <= min) 
            min = dist[v], min_index = v; 
  
    return min_index; 
} 
  
// A utility function to print the constructed distance array 
void printSolution(int dist[]) 
{ 
    printf("Vertex \t\t Distance from Source\n"); 
    for (int i = 0; i < V; i++) 
        printf("%d \t\t %d\n", i, dist[i]); 
} 

void printparent()
{
    for (int i = 0; i < end_node; i++){
        if(parent[i]){
             printf("%d --> ", parent[i]);
        }
    }
}

// Function that implements Dijkstra's single source shortest path algorithm 
// for a graph represented using adjacency matrix representation 
void dijkstra(int graph[V][V], int src) 
{ 
    int dist[V]; // The output array.  dist[i] will hold the shortest 
    // distance from src to i 
  
    bool sptSet[V]; // sptSet[i] will be true if vertex i is included in shortest 
    // path tree or shortest distance from src to i is finalized 
  
    // Initialize all distances as INFINITE and stpSet[] as false 
    for (int i = 0; i < V; i++) 
        dist[i] = INT_MAX, sptSet[i] = false; 
  
    // Distance of source vertex from itself is always 0 
    dist[src] = 0; 
    parent[src] = 0;
  
    // Find shortest path for all vertices 
    for (int count = 0; count < V - 1; count++) { 
        // Pick the minimum distance vertex from the set of vertices not 
        // yet processed. u is always equal to src in the first iteration. 
        int u = minDistance(dist, sptSet); 
  
        // Mark the picked vertex as processed 
        sptSet[u] = true; 
        
  
        // Update dist value of the adjacent vertices of the picked vertex. 
        for (int v = 0; v < V; v++) 
  
            // Update dist[v] only if is not in sptSet, there is an edge from 
            // u to v, and total weight of path from src to  v through u is 
            // smaller than current value of dist[v] 
            if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX 
                && dist[u] + graph[u][v] < dist[v]) {
                dist[v] = dist[u] + graph[u][v]; 
                parent[v] = u;
            }
    } 
  
    // print the constructed distance array 
    printSolution(dist); 
} 
  
// driver program to test above function 
int main() 
{ 
    /* Let us create the example graph discussed above */
    int graph[V][V] = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 }, 
                        { 4, 0, 8, 0, 0, 0, 0, 11, 0 }, 
                        { 0, 8, 0, 7, 0, 4, 0, 0, 2 }, 
                        { 0, 0, 7, 0, 9, 14, 0, 0, 0 }, 
                        { 0, 0, 0, 9, 0, 10, 0, 0, 0 }, 
                        { 0, 0, 4, 14, 10, 0, 2, 0, 0 }, 
                        { 0, 0, 0, 0, 0, 2, 0, 1, 6 }, 
                        { 8, 11, 0, 0, 0, 0, 1, 0, 7 }, 
                        { 0, 0, 2, 0, 0, 0, 6, 7, 0 } }; 
  
    dijkstra(graph, 0); 
    printparent();
  
    return 0; 
} 

程序打印出0到5之间正确的最短距离,也就是11,但是没有打印出正确的路线:

Vertex           Distance from Source
0                0
1                4
2                12
3                19
4                21
5                11
6                9
7                8
8                14
1 --> 2 --> 5 -->

0到5的正确最短路径应该是:

0 --> 7 --> 6 --> 5 -->

长度为 11。

我应该如何修复我的代码以打印正确的最短路径?

数组部分存储最短路径,代码如下:

int array[100];
int a;

void printparent(){
     n = end_node;
     while(n != 0){
          array[a] = n;
          printf("%s --> ", n);
          n = parent[n];
          a++;
     }
}

【问题讨论】:

  • 在printparent 中,您将parent[] 视为路径的线性数组,但该数组实际上是parent[v] == p 的映射。所以按照路线,u = end_node; while (u != 0) { print(u); u = parent[u]; }。这将为您提供正确的路径,但方向相反。

标签: c algorithm shortest-path dijkstra


【解决方案1】:

你的 printparent() 函数对我来说完全没有意义。

首先,考虑循环的迭代边界:

    for (int i = 0; i < end_node; i++){

只考虑节点 0 到 end_node 的父节点有何意义?最短路径可以很好地通过其他节点。

其次,考虑打印的条件:

        if(parent[i]){

parent 数组包含从 0 开始的顶点编号。该条件将始终跳过其父节点为节点 0 的节点,因此如果该路径包含节点 0(如您的那样),它将无法打印正确的最短路径。

此外,请考虑您打印父项的顺序,以及您打印的父项的选择。如果节点N 位于最短路径上,父节点P,那么您想在打印P 后立即打印N,但如果您只是遍历索引中的parent 数组,这只是偶然发生命令。并且没有理由期望这种方法会可靠地忽略添加到最短路径树中但不会出现在起始节点和结束节点之间的最短路径上的节点。

您需要一种完全不同的方法来打印最短路径。打印反向路径其实更自然:

  • 首先打印结束节点;
  • 在每个后续步骤中,打印parent[n],其中n 是上一次迭代中打印的节点
  • 在到达源节点时停止,或者如果您不想将源节点作为参数传递,则在到达没有父节点时停止

(当然,与parent[i] == 0 相比,您确实需要一种不同的方式来指定“没有父母”。)

要打印正向的路径,您需要首先按照描述向后追溯,然后以相反的顺序打印结果。您可以通过将它们存储在一个数组中然后对其进行反向迭代来做到这一点,或者通过递归地进行路径发现,在递归调用返回后打印每个节点。

【讨论】:

  • 感谢您的回复!我设法使用上面@M Oehm 注释中的代码向后打印路线,但由于while 函数正在循环,我如何将每个n 存储到不同的数组中而不影响循环中n 的值?
  • @c_struggler,我不太清楚你不确定哪一部分。如果您要练习收集数组中最短路径节点的选项,那么您需要 (1) 声明一个合适的数组,以及 (2) 声明并使用一个变量,您可以在其中跟踪其中有多少点到目前为止已填充(这也是下一个可用元素的索引)。这与n 或任何您选择调用的变量完全不同,您可以在其中沿路径跟踪节点标识符。
  • 好的,现在可以正常使用了,非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
  • 2017-11-08
  • 2016-07-30
  • 2016-07-13
  • 1970-01-01
  • 2012-06-23
相关资源
最近更新 更多