C ++:为较大的图

时间:2016-01-28 08:23:01

标签: c++ graph shortest-path

我在图上解决了一些问题。它需要存储N个节点的权重(N <= 50000)。我不能使用矩阵来存储图形的权重(因为不能分配50000x50000)。你知道其他任何方式吗?感谢。

4 个答案:

答案 0 :(得分:2)

我存储不太密集的图表的首选方法是使用邻接列表。 但是,使用邻接列表的缺点是您无法直接检查节点 i 是否连接到节点 j 。相反,您遍历节点 i 的所有邻居(如果 j 与节点i连接,它将最终显示在其中)。去除边缘也是不切实际的。我在对图表进行广度优先或深度优先搜索时使用它,因为只对邻居集合感兴趣而不是对两个特定节点是否连接感兴趣。

总结:

  1. 只占用你边缘的内存(这是你想要的),但至少和节点一样多。
  2. 易于遍历任何节点的egdes,即始终每个邻居的恒定时间
  3. 要检查两个节点 i j 是否已连接,您需要遍历节点 i j <的整个邻居列表/ em>的。如果一个节点连接到几乎所有其他节点并且如果它连接到少数
  4. 则便宜,这是不好的
  5. 对于大型社区来说,移除边缘也是昂贵的(在节点的邻居数量的最差线性时间内),对于小型社区而言便宜。
  6. 插入边缘非常便宜(恒定时间)
  7. 举个例子(首先是所有权重1)

    using Graph = std::vector<std::vector<int>>;
    

    现在您可以使用

    创建 n 节点的图形
    Graph mygraph(n);
    

    如果您想连接节点 i j ,只需执行

    mygraph[i].push_back(j);
    mygraph[j].push_back(i);
    

    要遍历某个节点的所有边缘,您只需执行

    即可
    for (int neighbor : mygraph[i]) {
        std::cout << i << " is connected with " << neighbor << std::endl;
    }
    

    现在对于一般权重更难的问题:

    using Graph = std::vector<std::vector<std::pair<int, double>>>;
    Graph myWeightedgraph(n);
    

    现在您可以非常轻松地插入边缘

    double weight = 123.32424;
    myWeightedgraph[i].push_back({j, w});
    myWeightedgraph[j].push_back({i, w});
    

    对于遍历:

    for (auto& neighbor : myWeightedgraph[i]) {
        std::cout << i << " is connected with " << neighbor.first << " with weight " << neighbor.second << std::endl;
    }
    

答案 1 :(得分:0)

如果两个节点之间不能有多条边:

首先想到一些系统如何给每个现有边缘一个唯一的数字 例如。对于N个节点和节点号在0和N-1之间,节点A和节点B之间的边可以只有A*N+B(例如,在uint64_t变量中)

然后制作std::map个边,计算出的数字为关键,权重为值。那里的大多数操作都有对数时间,这个时间不如2D数组好,但仍然很好,而且你需要更少的内存。

答案 2 :(得分:0)

通常有两种表示图形的方法。如你所述,第一个是使用邻接矩阵。专业人员可以轻松查看是否连接了两个节点ij。缺点是空间复杂度( O(V²),其中 V 是顶点数。)

另一个是邻接列表:对于每个顶点,您存储一个邻接列表,其中包含从该顶点出来的每个边。显然,空间复杂度为 O(V + E),其中 V 是顶点数, E 是边数。

请注意,您可以将边存储在邻接贴图而不是列表中。假设您为每个边提供一个唯一的整数键。如果您的图表稀疏,则std::unordered_map很适合,因为碰撞几率很低。这将为您提供给定边缘的平均 O(1)查找和插入复杂度。

如果您的图形可以有大量边缘,那么只需使用依赖于红黑树的常规std::map。然后,您将在插入或查找节点时具有对数复杂度。

以下是一些示例代码:

struct Edge {
    int weight;
    int start, end;
}
struct Vertex {
    int key;
    std::unordered_map<int, Edge> adjacency_map;
}
struct Graph {
    std::vector<Edge> edges;
}

答案 3 :(得分:-1)

您无法将大小为10 ^ 9的数组分配为静态内存。你应该使用malloc代替。更好的是,您可以使用adjacency list来存储图表。