我在图上解决了一些问题。它需要存储N个节点的权重(N <= 50000)。我不能使用矩阵来存储图形的权重(因为不能分配50000x50000)。你知道其他任何方式吗?感谢。
答案 0 :(得分:2)
我存储不太密集的图表的首选方法是使用邻接列表。 但是,使用邻接列表的缺点是您无法直接检查节点 i 是否连接到节点 j 。相反,您遍历节点 i 的所有邻居(如果 j 与节点i连接,它将最终显示在其中)。去除边缘也是不切实际的。我在对图表进行广度优先或深度优先搜索时使用它,因为只对邻居集合感兴趣而不是对两个特定节点是否连接感兴趣。
总结:
举个例子(首先是所有权重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)
通常有两种表示图形的方法。如你所述,第一个是使用邻接矩阵。专业人员可以轻松查看是否连接了两个节点i
和j
。缺点是空间复杂度( 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来存储图表。