使用深度优先搜索 (DFS) C++ 查找图中两个节点之间是否存在路径

发布于 2025-01-11 18:04:37 字数 1280 浏览 1 评论 0原文

我正在尝试实现深度优先搜索(DFS),如果图中两个节点之间存在路径,则使用递归返回布尔值。下面是我的实现。边缘输入采用向量数组的形式。

我尝试调试程序以检测到底哪里出错了,但我不知道为什么当我调用 return validPath_helper(n, i, destination,visited, adjList);validPath 函数中执行 code> 函数。

bool validPath_helper(int n, int source, int destination, vector<bool> visited, vector<vector<int>> adjList){
    visited[source] = true;

    if(adjList[source][destination]){
        return true;
    }

    for(int i=0; i<adjList[source].size(); i++){
        if(adjList[source][i]){
            return validPath_helper(n, i, destination, visited, adjList);
        }
    }
    return false;
}

bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
    vector<bool> visited(n, false);
    vector<vector<int>> adjList(n);

    int u, v;
    for(int i=0; i<edges.size(); i++){
        u = edges[i][0];
        v = edges[i][1];
        adjList[u].push_back(v);
        adjList[v].push_back(u);
    }

    for(int i=source; i<n; i++){
        if(!visited[i]){
            return validPath_helper(n, i, destination, visited, adjList);
        }
    }
    return false;
}

任何帮助将不胜感激!

I'm trying to implement the Depth First Search(DFS) suing recursion to return a boolean value if a path exists between two Nodes in a graph. Below is my implementation. The edges input is in the form of a Vector array.

I tried debugging the program to detect where exactly I am going wrong, but I don't know why it gives a segmentation fault as soon as I call return validPath_helper(n, i, destination, visited, adjList); function in the validPath function after checking if the Node is visited or not.

bool validPath_helper(int n, int source, int destination, vector<bool> visited, vector<vector<int>> adjList){
    visited[source] = true;

    if(adjList[source][destination]){
        return true;
    }

    for(int i=0; i<adjList[source].size(); i++){
        if(adjList[source][i]){
            return validPath_helper(n, i, destination, visited, adjList);
        }
    }
    return false;
}

bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
    vector<bool> visited(n, false);
    vector<vector<int>> adjList(n);

    int u, v;
    for(int i=0; i<edges.size(); i++){
        u = edges[i][0];
        v = edges[i][1];
        adjList[u].push_back(v);
        adjList[v].push_back(u);
    }

    for(int i=source; i<n; i++){
        if(!visited[i]){
            return validPath_helper(n, i, destination, visited, adjList);
        }
    }
    return false;
}

Any Help would be appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

阳光下的泡沫是彩色的 2025-01-18 18:04:37

段错误通常是由于访问未分配的内存而发生的,因此您应该首先调查这一点。您说 validPath_helper 正在触发 seg 错误,因此您应该检查该函数。

在您的情况下,罪魁祸首是这一行:

if(adjList[source][destination]){
    return true;
}

这里您想检查源节点和目标节点之间是否存在边。但是,如果您回顾一下创建邻接列表的方式,您会发现它是一个向量的向量,对于每个节点,我们都有一个它有边的节点列表。

例如下图:

1 - 2
0 - 1
1 - 3

邻接列表将是:

0 -> 1
1 -> 0 2 3
2 -> 1
3 -> 1

让我们以源 2 和目标 3 为例。
现在,当您的 validPath_helper 被调用时,它将检查 adjList[2][3] 但正如您在上面看到的 adjList[2] 的长度仅为 1,因此没有第四个元素检查(3 是索引,因此是第四个元素)。这是您的段错误的原因。

这也会导致代码中出现一个完全不同的问题,即您想要检查 2 和 3 之间是否存在边,而是检查 2 列表的第 4 个位置是否存在非零元素。

您可以通过几种方法解决这个问题。

方法 # 1

而不是

if(adjList[source][destination]){
    return true;
}

try

for (int index = 0; index < adjList[source].size(); index++) {
    if (adjList[source][index] == destination)
        return true;
}

您需要在 validPath_helper 函数的两个位置进行此更改。

方法#2

在大图的情况下,上述方法会增加程序的运行时间,如果您关心运行时间并且了解哈希列表,则此方法更好。

#include <unordered_set> // at top

bool validPath_helper(int n, int source, int destination, vector<bool> visited, vector<unordered_set<int>> adjList){
    visited[source] = true;

    if(adjList[source].find(destination) != adjList[source].end()){
        return true;
    }

    for(int i: adjList[source]){
        if (!visited[i] && validPath_helper(n, i, destination, visited, adjList)) {
            return true;
        }
    }
    return false;
}

bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
    vector<bool> visited(n, false);
    vector<unordered_set<int>> adjList(n); 

    int u, v;
    for(int i=0; i<edges.size(); i++){
        u = edges[i][0];
        v = edges[i][1];
        adjList[u].insert(v); 
        adjList[v].insert(u);
    }

    return validPath_helper(n, i, destination, visited, adjList);
}

您的代码中还有更多错误:

  1. 两个函数中都有一些不必要的循环。
  2. 您将访问设置为 true,但在新节点上调用 DFS 之前不检查它。
  3. 您返回第一个 DFS 结果并且不检查其他子节点。 (由于在 validPath_helper 函数中返回 validPath_helper 调用。

也请研究这些问题,如果您遇到困难,请参阅上面的方法#2。

Seg faults usually occur due to access of un-allocated memory so that's what you should investigate first. You said that the validPath_helper is triggering the seg fault, so you should check that function.

In your case the culprit is this line :

if(adjList[source][destination]){
    return true;
}

Here you wanted to check that whether there is an edge between source node and destination node. But if you check back to how you created your adjacency list, you will see it is a vector of vectors that is for every node we have a list of nodes it has edges to.

For example the following graph:

1 - 2
0 - 1
1 - 3

The adjacency list will be :

0 -> 1
1 -> 0 2 3
2 -> 1
3 -> 1

Let's take source 2 and destination 3.
Now when your validPath_helper is called it will check adjList[2][3] but as you see above length of adjList[2] is only 1 so there is no 4th element to check (3 is index so 4th element). This is the cause of your seg fault.

This also leads to an entirely different problem in your code that you want to check whether edge exists between 2 and 3 but instead you check whether there is a non-zero element at 4th position of 2's list.

You can fix this a couple of ways.

Way # 1

Instead of

if(adjList[source][destination]){
    return true;
}

try

for (int index = 0; index < adjList[source].size(); index++) {
    if (adjList[source][index] == destination)
        return true;
}

You need to make this change in both the places of your validPath_helper function.

Way # 2

The above method increases the runtime of your program in case of big graphs, if you are concerned about runtime and know about hashlists this method is better.

#include <unordered_set> // at top

bool validPath_helper(int n, int source, int destination, vector<bool> visited, vector<unordered_set<int>> adjList){
    visited[source] = true;

    if(adjList[source].find(destination) != adjList[source].end()){
        return true;
    }

    for(int i: adjList[source]){
        if (!visited[i] && validPath_helper(n, i, destination, visited, adjList)) {
            return true;
        }
    }
    return false;
}

bool validPath(int n, vector<vector<int>>& edges, int source, int destination) {
    vector<bool> visited(n, false);
    vector<unordered_set<int>> adjList(n); 

    int u, v;
    for(int i=0; i<edges.size(); i++){
        u = edges[i][0];
        v = edges[i][1];
        adjList[u].insert(v); 
        adjList[v].insert(u);
    }

    return validPath_helper(n, i, destination, visited, adjList);
}

There were a couple more bugs in your code :

  1. Some unnecessary loops in both your functions.
  2. You set visited to true but do not check it before calling DFS on new nodes.
  3. You return the first DFS result and don't check other child nodes. (Due to return validPath_helper call in validPath_helper function.

Look into these issues too, refer to way # 2 above if you are stuck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文