如何返回图中2个节点之间所有可能路径的2D数组? (C ++)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何返回图中2个节点之间所有可能路径的2D数组? (C ++)相关的知识,希望对你有一定的参考价值。

我从网上获取了以下代码,供我参考。在int main() {}中,它首先将边缘添加到图形中,然后使用调用函数,该函数使用递归对输出所有可能的路径。

// C++ program to print all paths from a source to destination. 
#include<iostream> 
#include <list> 
using namespace std; 

// A directed graph using adjacency list representation 
class Graph 
{ 
    int V; // No. of vertices in graph 
    list<int> *adj; // Pointer to an array containing adjacency lists 

    // A recursive function used by printAllPaths() 
    void printAllPathsUtil(int , int , bool [], int [], int &); 

public: 
    Graph(int V); // Constructor 
    void addEdge(int u, int v); 
    void printAllPaths(int s, int d); 
}; 

Graph::Graph(int V) 
{ 
    this->V = V; 
    adj = new list<int>[V]; 
} 

void Graph::addEdge(int u, int v) 
{ 
    adj[u].push_back(v); // Add v to u’s list. 
} 

// Prints all paths from 's' to 'd' 
void Graph::printAllPaths(int s, int d) 
{ 
    // Mark all the vertices as not visited 
    bool *visited = new bool[V]; 

    // Create an array to store paths 
    int *path = new int[V]; 
    int path_index = 0; // Initialize path[] as empty 

    // Initialize all vertices as not visited 
    for (int i = 0; i < V; i++) 
        visited[i] = false; 

    // Call the recursive helper function to print all paths 
    printAllPathsUtil(s, d, visited, path, path_index); 
} 

// A recursive function to print all paths from 'u' to 'd'. 
// visited[] keeps track of vertices in current path. 
// path[] stores actual vertices and path_index is current 
// index in path[] 
void Graph::printAllPathsUtil(int u, int d, bool visited[], 
                            int path[], int &path_index) 
{ 
    // Mark the current node and store it in path[] 
    visited[u] = true; 
    path[path_index] = u; 
    path_index++; 

    // If current vertex is same as destination, then print 
    // current path[] 
    if (u == d) 
    { 
        for (int i = 0; i<path_index; i++) 
            cout << path[i] << " "; 
        cout << endl; 

    } 
    else // If current vertex is not destination 
    { 
        // Recur for all the vertices adjacent to current vertex 
        list<int>::iterator i; 
        for (i = adj[u].begin(); i != adj[u].end(); ++i) 
            if (!visited[*i]) 
                printAllPathsUtil(*i, d, visited, path, path_index); 
    } 

    // Remove current vertex from path[] and mark it as unvisited 
    path_index--; 
    visited[u] = false; 
} 

// Driver program 
int main() 
{ 
    // Create a graph given in the above diagram 
    Graph g(4); 
    g.addEdge(0, 1); 
    g.addEdge(0, 2); 
    g.addEdge(0, 3); 
    g.addEdge(2, 0); 
    g.addEdge(2, 1); 
    g.addEdge(1, 3); 

    int s = 2, d = 3; 
    cout << "Following are all different paths from " << s 
        << " to " << d << endl; 
    g.printAllPaths(s, d); 

    return 0; 
} 

如何修改此代码,以使函数返回list<list<int> >而不是打印路径?这样我可以使用此列表进行进一步处理?

谢谢!

答案

一种方法是通过引用util函数传递列表。每当到达终点时,只需列出路径,然后将其推入结果列表即可。

代码应该看起来像这样:

// C++ program to print all paths from a source to destination. 
#include<iostream> 
#include <list> 
using namespace std;

// A directed graph using adjacency list representation 
class Graph
{
    int V; // No. of vertices in graph 
    list<int>* adj; // Pointer to an array containing adjacency lists 

    // A recursive function used by printAllPaths() 
    void printAllPathsUtil(int, int, bool[], int[], int&, list<list<int>>&);

public:
    Graph(int V); // Constructor 
    void addEdge(int u, int v);
    list<list<int>> printAllPaths(int s, int d);
};

Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}

void Graph::addEdge(int u, int v)
{
    adj[u].push_back(v); // Add v to u’s list. 
}

// Prints all paths from 's' to 'd' 
list<list<int>> Graph::printAllPaths(int s, int d)
{
    // Mark all the vertices as not visited 
    bool* visited = new bool[V];

    // Create an array to store paths 
    int* path = new int[V];
    int path_index = 0; // Initialize path[] as empty 

    // Initialize all vertices as not visited 
    for (int i = 0; i < V; i++)
        visited[i] = false;

    list<list<int>> result;

    // Call the recursive helper function to print all paths 
    printAllPathsUtil(s, d, visited, path, path_index, result);

    return result;
}

// A recursive function to print all paths from 'u' to 'd'. 
// visited[] keeps track of vertices in current path. 
// path[] stores actual vertices and path_index is current 
// index in path[] 
void Graph::printAllPathsUtil(int u, int d, bool visited[],
    int path[], int& path_index, list<list<int>>& result)
{
    // Mark the current node and store it in path[] 
    visited[u] = true;
    path[path_index] = u;
    path_index++;

    // If current vertex is same as destination, then print 
    // current path[] 
    if (u == d)
    {
        list<int> tempList;
        for (int i = 0; i < path_index; i++)
            tempList.push_back(path[i]);
        result.push_back(tempList);
    }
    else // If current vertex is not destination 
    {
        // Recur for all the vertices adjacent to current vertex 
        list<int>::iterator i;
        for (i = adj[u].begin(); i != adj[u].end(); ++i)
            if (!visited[*i])
                printAllPathsUtil(*i, d, visited, path, path_index, result);
    }

    // Remove current vertex from path[] and mark it as unvisited 
    path_index--;
    visited[u] = false;
}

// Driver program 
int main()
{
    // Create a graph given in the above diagram 
    Graph g(4);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(0, 3);
    g.addEdge(2, 0);
    g.addEdge(2, 1);
    g.addEdge(1, 3);

    int s = 2, d = 3;
    cout << "Following are all different paths from " << s
        << " to " << d << endl;

    list<list<int>> result = g.printAllPaths(s, d);

    for (auto path : result)
    {
        for (auto node : path)
            std::cout << node << ' ';
        std::cout << std::endl;
    }

    return 0;
}

输出:

Following are all different paths from 2 to 3
2 0 1 3
2 0 3
2 1 3

我不建议使用list tho。我认为使用std::vector在速度和内存方面会更好。但是由于您要求输入list,所以此代码返回一个列表。阿洛斯,我不得不说我没有阅读代码,只是更改了需要更改的内容才能返回列表。

这里是另一个执行相同操作但使用std::vector的代码。

#include <iostream>
#include <vector>

class Graph
{
    std::vector<std::vector<int>> graph;
    std::vector<std::vector<int>> paths;
    std::vector<bool> visited;

    void DFS(int currentNode, int destNode, std::vector<int>& currentPath)
    {
        visited[currentNode] = true;
        currentPath.push_back(currentNode);

        if (currentNode == destNode)
            paths.push_back(currentPath);
        else
        {
            for (auto node : graph[currentNode])
                if (!visited[node])
                    DFS(node, destNode, currentPath);
        }

        currentPath.pop_back();
        visited[currentNode] = false;
    }

public:

    Graph(int size)
    {
        graph.resize(size);
        visited.resize(size);
    }

    void addEdge(int from, int to)
    {
        graph[from].push_back(to);
    }

    std::vector<std::vector<int>> GetAllPossiblePaths(int source, int dest)
    {
        paths.clear();
        std::fill(visited.begin(), visited.end(), false);

        std::vector<int> temp;

        DFS(source, dest, temp);

        return paths;
    }
};

int main()
{
    Graph g(4);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(0, 3);
    g.addEdge(2, 0);
    g.addEdge(2, 1);
    g.addEdge(1, 3);

    auto result = g.GetAllPossiblePaths(2, 3);

    for (auto& path : result)
    {
        for (auto node : path)
            std::cout << node << ' ';
        std::cout << std::endl;
    }
}

以上是关于如何返回图中2个节点之间所有可能路径的2D数组? (C ++)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法之深入解析“找到最终的安全状态”的求解思路与算法示例

循环无向图中的所有可能路径

如何用分组方法计算2层对象之间的拓扑?

求两点间所有路径

无向图中求两定点之间所有路径。图用二维数组存储。最好用c语言、给我解题思路也行。谢谢

使用 DFS 查找两个节点之间的所有路径