【发布时间】:2023-03-26 13:10:01
【问题描述】:
我正在研究一种数据结构的擦除方法,该方法具有硬编码的最大元素数 N,它依赖于 std::array 来避免堆内存。虽然std::array 只包含 N 个元素,但其中只有一些 M 是“相关”元素,其中 M 小于或等于 N。例如,如果 N 为 10,则数组如下所示:
std::array<int, N> elements = { 0, 1, 2, -1, 4, -1, 6, -1, -1, 9 };
...如果 M 为 7,则只有前 7 个元素是“相关的”,而其他元素被视为垃圾(结尾 { -1, -1, -9 } 是垃圾)。我在这里使用int 作为SO 示例,但实际程序存储实现operator== 的对象。下面是一个删除所有 -1 并更新 M 的工作示例:
#include <algorithm>
#include <array>
#include <iostream>
constexpr unsigned N = 10;
unsigned M = 7;
std::array<int, N> elements = { 0, 1, 2, -1, 4, -1, 6, -1, -1, 9 };
int main() {
for (unsigned i = 0; i < M; ++i)
std::cout << elements[i] << ' ';
std::cout << '\n';
auto newEnd = std::remove_if(
std::begin(elements), std::begin(elements) + M,
[](const auto& element) {
return -1 == element;
}
);
unsigned numDeleted = M - std::distance(std::begin(elements), newEnd);
M -= numDeleted;
std::cout << "Num deleted: " << numDeleted << '\n';
for (unsigned i = 0; i < M; ++i)
std::cout << elements[i] << ' ';
std::cout << '\n';
return 0;
}
我的问题是std::remove_if 的渐近复杂度是多少?我想在std::remove_if 和std::distance 之间,总体上是O(2M) 或O(M),而std::remove_if 是一个更昂贵的操作。但是我不确定std::remove_if 是否为 O(N * M),因为每次删除都会移动元素
编辑:为清楚起见,我知道这应该应用谓词 M 次,但我想知道每次谓词为真时是否应用 N 班次
【问题讨论】:
-
无论如何
std::begin(elements), &elements[M]是实现特定的行为,因为C++ 标准说std::begin(elements)将返回elements.begin(),这反过来又返回一个std::array::iterator,它是实现特定类型,而&elements[M]是一个指针类型 -
@Danh,怎么可能是 O(1)?如果我有一个大小为 100 的数组,90 个元素是“相关的”,并且我认为 90 是 M,那么
std::remove至少是 O(M) -
@Danh Complexity 在这里肯定不是
O(1),因为它取决于N和M,使它们保持不变并不会改变程序复杂性取决于这两个值的事实。 -
@asimes
std::begin(elements) + M应该可以工作并且是标准的。 -
@Danh 如果你有 “正是
std::distance(first, last)谓词的应用程序。”,那么它肯定不是恒定的,因为它取决于last和first。
标签: c++ asymptotic-complexity remove-if