【问题标题】:Need a faster way to create an adjacency list in c++需要一种更快的方法在 C++ 中创建邻接列表
【发布时间】:2022-01-13 00:33:12
【问题描述】:

我正在尝试从顶点、边和单个连接的输入创建邻接列表。输入如下所示:

3 2(顶点、边)

1 2(连接)

1 3

现在,我的代码是

int vertices, edges;
scanf("%d %d", &vertices, &edges);

vector<vector<int>> storage[vertices+1];
for (int i = 0; i < edges; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    if (find(storage[b].begin(), storage[b].end(), a) != storage[b].end() == false) {
        storage[b].push_back(a);
    }
    if (find(storage[a].begin(), storage[a].end(), b) != storage[a].end() == false) {
        storage[a].push_back(b);
    }
}

是否有更快/更有效的方法来做到这一点,或者这是最好的方法?

【问题讨论】:

  • vector&lt;int&gt; storage[vertices+1]; 不是标准 C++。仅当您使用编译器特定的 C++ 扩展时,才可能使用可变长度数组。另见Why aren't variable-length arrays part of the C++ standard?
  • vector&lt;int&gt; storage[vertices+1]; -- 我猜你没有意识到std::vector 的用途。如果你这样做了,那么这应该是std::vector&lt;std::vector&lt;int&gt;&gt; storage(vertices + 1);
  • 奇怪。它们都有效。
  • 这并不奇怪。这是一个编译器扩展,它完全适用于您的编译器。但它不便携,因此不受欢迎。
  • 尝试将 vertices 设置为 10 亿,看看你如何处理这个可变长度数组......

标签: c++ arrays adjacency-list


【解决方案1】:

几乎不可能对这类问题给出一般性的答案,因为执行时间将取决于可能相差几个数量级的因素。例如,填充数据结构的成本可能与您之后对它的处理相比微不足道。另请参阅this answer,我将引用其最终建议:

与往常一样,如果您要实现高性能计算程序,分析和测量运行时间和内存以找到实际问题实现的瓶颈是关键。

该答案还提到了您可以考虑的一些不同的 STL 容器。 Herehere 是关于这个主题的另外两个问题。

话虽如此,在尝试改进任何事情之前先进行衡量。例如,如果分段读取输入成为瓶颈,您可以考虑在进一步处理之前将其全部读入std::string

为了完整起见,我可能会像这样用标准 C++ 编写您当前的代码:

#include <algorithm>
#include <iostream>
#include <vector>

// ...

// Speeds up std i/o, but don't mix the C and C++ interfaces afterwards
std::ios_base::sync_with_stdio(false);

int vertices, edges;
std::cin >> vertices >> edges;

std::vector<std::vector<int>> storage(vertices + 1);
// When filling vectors with push_back/emplace_back, it's best to call 
// reserve first. If using 1-based indexing, skip the first vector:
for (auto v = std::next(storage.begin()); v != storage.end(); ++v)
    v->reserve(vertices - 1);

// With C++20 support you can #include <ranges> and write
for (auto& v : storage | std::views::drop(1))
    v.reserve(vertices - 1);

auto found = [](auto const& vector, auto value) {
    return std::find(vector.begin(), vector.end(), value) != vector.end();
// or, with C++20: std::ranges::find(vector, value) != vector.end()
};

for (int a, b, i = 0; i < edges && std::cin >> a >> b; ++i) {
    if (!found(storage[b], a))
        storage[b].push_back(a);
    // ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多