【问题标题】:Dijkstra SDSP AlgorithmDijkstra SDSP 算法
【发布时间】:2021-07-10 11:24:13
【问题描述】:

我正在尝试使用邻接列表和 PQ 作为最小堆来实现单目的地最短路径的 Dijkstra 算法。输出必须显示所有顶点到目标顶点的路径,如果路径存在,如果存在,则它的总和(最短),如果不存在,则没有路径。 Link to entire code

输入格式:

  • 第一行是顶点数,n
  • 从第二行开始:(顶点从 1 到 n)
    • 第一列是顶点。
    • 之后,多对,
  • test.txt
4
1 2 4 3 5 4 5
4 1 7 3 3
2 1 3 4 10 

根据 GDB 显示,在 extractMin 函数中发现了 Segmentation fault。

Program received signal SIGSEGV, Segmentation fault.
0x00401746 in extractMin ()

客户端.c

从 text.txt 文件中提取输入并创建有向图

FILE *fptr = fopen("test.txt", "r");
    if (fptr == NULL) exit(1);

    int n;
    if (fscanf(fptr, "%d", &n) == 1 && n > 0)
    {
        Graph *graph = createGraph(n);
        int c;
        while ((c = fgetc(fptr)) != EOF && c != '\n');
        char *line = NULL;      
        size_t len = 0;        

        while (getline(&line, &len, fptr) > 0)
        {
            char *cur = line;
            int ccs = 0;
            int v1;

            if (sscanf(cur, "%d%n", &v1, &ccs) == 1)
            {
                cur += ccs;
                int v2;
                int w;
                while (sscanf(cur, "%d %d%n", &v2, &w, &ccs) == 2)
                {
                    addEdge(graph, v1, v2, w);
                    cur += ccs;
                }

                fputc('\n', stdout);
            }

        }
        free(line);
        for (int i = 0; i < n; i++)
            dijkstra(graph, i);
    }

服务器.c

struct MinHeapNode* extractMin(MinHeap* minHeap)
{
    if (isEmpty(minHeap))
        return NULL;
 
    struct MinHeapNode* root = minHeap->array[0];
    struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
    minHeap->array[0] = lastNode;
 
    minHeap->pos[root->v] = minHeap->size-1;
    minHeap->pos[lastNode->v] = 0;
 
    --minHeap->size;
    minHeapify(minHeap, 0);
 
    return root;
}
void dijkstra(Graph* graph, int dest)
{
    int v = graph->vertices;
    int distance[v]; 
    int pathFollow[1000]={0};
    int ind = 0;

    MinHeap* minHeap = createMinHeap(v);
 
    for (int i = 0; i < v; ++i)
    {
        distance[v] = INT_MAX;
        minHeap->array[v] = newMinHeapNode(v, distance[v]);
        minHeap->pos[v] = v;
    }
 
    minHeap->array[dest] = newMinHeapNode(dest, distance[dest]);
    minHeap->pos[dest] = dest;
    distance[dest] = 0;
    decreaseKey(minHeap, dest, distance[dest]);
 
    minHeap->size = v;

    while (!isEmpty(minHeap))
    {
        struct MinHeapNode* minHeapNode = extractMin(minHeap);
        int u = minHeapNode->v;
        AdjListNode* path = graph->array[u].head;
        while (path != NULL)
        {
            int v = path->vertex;
            if (isInMinHeap(minHeap, v) && distance[u] != INT_MAX &&
              path->weight + distance[u] < distance[v])
            {
                distance[v] = distance[u] + path->weight;
                if(pathFollow[ind-1] != u)
                    pathFollow[ind++]=u;
                decreaseKey(minHeap, v, distance[v]);
            }
            path = path->next;
        }
    }
    printArr(distance, v, pathFollow, dest);
}

void printArr(int dist[], int n, int pathFollow[], int dest)
{
    printf("%d", dest+1);
    int j = 0;
    if(dist[n-1]!=0 && dist[n-1] < 100000000) 
    {
        int k = j;
        printf(" %d", pathFollow[k]+1);
        while(pathFollow[j]!=0) 
        {
        printf(" %d", pathFollow[j++]);
        }
        printf(" %d %d\n",n, dist[n-1]);
    }
    else
    {
        printf("NO PATH\n");
    }
}


【问题讨论】:

  • 尝试通过在代码中添加断点(这里是tutorial)来运行您的代码here,看看问题出在哪里。
  • 如果我们不知道代码实际出错的地方,dijkstra 的输入是什么,我们将无法为您提供太多帮助。
  • 如果你没看到,我把整个代码链接放了。我应该显示 valgrind 显示的内容吗?
  • 我在 VSCode 上尝试了 gdb,它在 extractMin 中抛出了 seg 错误,我将编辑帖子
  • 编辑帖子以在帖子中提供minimal reproducible example。链接可用于补充信息,但重现问题所需的所有信息都应包含在问题本身中。 Stack Overflow 不是个人调试服务。它旨在创建一个持久的问题和答案存储库,以帮助未来的读者。但是到外部站点的链接会中断,从而使依赖于它们的问题对其他人毫无用处。所以一切都必须在帖子中。调试你的程序是一个附带的好处,而要求调试大量代码是一种滥用。

标签: c algorithm segmentation-fault dijkstra


【解决方案1】:

我不打算调试整个程序,但这里有一些错误:

  1. 你创造

     Graph *graph = createGraph(n);
    

然后正在访问graph-&gt;array[src].head。

这是一个问题,因为 n 只是顶点的总数,在您的情况下为 4,但是当使用 4 1 7 之类的东西调用 addEdge() 时,这就是堆缓冲区溢出。您需要考虑您创建的 0-indexed 数组。

  1. 另一个溢出问题,这次是堆栈缓冲区,将在:

    int v = graph->vertices;
    int distance[v];
    

但是这被称为

distance[v] = INT_MAX;

再次不考虑0-indexed 数组。此外,该代码似乎可疑,我相信应该是 distance[i] = INT_MAX。

请查看您自己的代码以了解更多此类错误,尤其是数组索引溢出,使用Address Sanitizers 检查代码是否存在内存错误,逐步检查程序的每一行,看看是否确实发生了预期的情况。你提到了extractMin() 周围的程序错误。检查它是否正在访问它应该访问的内存。 SIGSEGV 表示非法内存访问。 struct MinHeapNode* root 是否指向您分配的内容? struct MinHeapNode* lastNode 是否指向您分配的内容?

【讨论】:

  • 我一定会在这里尝试更新。它也可能对人们有所帮助
猜你喜欢
  • 1970-01-01
  • 2021-03-13
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多