找出向量中的所有元素是假还是真 c++ 的最快方法
Fastest way to find out if all elements in a vector are false or true c++?
我想知道是否有一种快速的方法可以找出向量中的所有元素是假的还是真的?就像而不是使用循环检查每个元素?
清楚起见,我会利用新算法
:// all true
std::all_of(vec.begin(), vec.end(), [](bool v) { return v; });
// all false
std::all_of(vec.begin(), vec.end(), [](bool v) { return !v; });
std::none_of(vec.begin(), vec.end(), [](bool v) { return v; });
如果不实际检查向量的每个元素,就无法确定向量中的所有元素是否为真。最好的情况是,你以不同的方式重新解释内存,一次检查一个以上的元素,但你仍然必须检查所有内容,直到找到一个不合格的元素。
最简单的IMO是免费find
函数
if (std::find(begin(v), end(v), true) == end(v)) // All false
您也可以使用 std::accumulate()
:
int sum = std::accumulate(std::begin(v), std::end(v), 0);
if (sum == v.size()) {
// All true
}
else if (sum) {
// Any true, any false
}
else {
// All false
}
这需要循环,但至少会利用短周期行为。
bool all = true;
std::vector<bool>::iterator it = myVec.begin();
while(all && it != myVec.end()) // Stops early if it hits a false
{
all &= *it;
++it;
}
如果all
是true
,向量中的所有元素都是真的。如果all
为假,则至少有一个元素未true
。
我也同意最坏的情况是必须检查每个单独的元素,但对于所有其他情况,我建议改写这个问题:
我的收藏中的所有元素都一样吗?如果是这样,价值是多少。
在这两种情况下,这将提前返回,您就完成了。否则,还必须检查元素的值(真或假(。
为此,我建议看这里。
我想更概括一下我的答案:这可以使用任何 N 个互斥谓词 A1、... 、AN 来完成,我想检查我的集合。为此,我将需要一个函数,给定我集合的一个元素,返回该元素的谓词 Ai 的一些标识符(以及检查谓词相等的方法(。
然后我可以再次应用上述方案。
我认为最有效的是:
if(v.find(v.begin(), v.end(), true) == v.end())
// All false
if(v.find(v.begin(), v.end(), false) == v.end())
// All true
对于大向量,更有效的选择是用vector<bitset>
替换vector<bool>
。然后,您可以简单地将 any_of()
算法与调用 bitset
成员函数的 lambda 函数结合使用any()
(或类似地用于 all_of()
和 all()
(。
int n = 2000000000, i = 623;
vector<bitset<256>> bits((n + 255) / 256);
bits[i >> 8][i & 0xFF] = true;
cout << bits[i >> 8][i & 0xFF] << endl;
if (any_of(bits.begin(), bits.end(),
[](const bitset<256>& bs) { return bs.any(); })) {
cout << "at least one bit set" << endl;
}
for (auto& bs : bits) {
bs.set();
}
if (all_of(bits.begin(), bits.end(),
[](const bitset<256>&bs) { return bs.all(); })) {
cout << "all bits set" << endl;
}
在我对 20 亿个元素(发布版本 VS2022(的计时测试中,any_of()
或上述all_of()
需要 20 毫秒(如果any_of()
提前爆发,则更快(。而对于vector<bool>
,它们需要 2200 毫秒。大约 100 倍加速。设置所有位需要36ms,而vector<bool>
为1930ms,大约是50倍的加速。
界面有点混乱,所以如果你想清理它,你可以把它包装在模板类中:
template <size_t bits_per_bitset, int lg_bits_per_bitset>
class dynamic_bitset {
public:
dynamic_bitset(int n)
: v((n + bits_per_bitset - 1)/ bits_per_bitset) { }
constexpr bool operator[](int i) const {
return v[i >> lg_bits_per_bitset][i & ((1 << lg_bits_per_bitset) - 1)];
}
auto operator[](int i) {
return v[i >> lg_bits_per_bitset][i & ((1 << lg_bits_per_bitset) - 1)];
}
bool any() {
return any_of(v.begin(), v.end(),
[](const std::bitset<bits_per_bitset>& bs) { return bs.any(); });
}
bool all() {
return all_of(v.begin(), v.end(),
[](const std::bitset<bits_per_bitset>& bs) { return bs.all(); });
}
void set() { for (auto& bs : v) bs.set(); }
void reset() { for (auto& bs : v) bs.reset(); }
void flip() { for (auto& bs : v) bs.flip(); }
private:
std::vector<std::bitset<bits_per_bitset>> v;
};
现在使用它就像这样简单:
int n = 2000000000, i = 623;
dynamic_bitset<256, 8> bits(n);
bits[i] = true;
cout << bits[i] << endl;
if (bits.any()) {
cout << "at least one bit set" << endl;
}
bits.set();
if (bits.all()) {
cout << "all bits set" << endl;
}
如果我增加模板参数,它会变得更快一些,但如果n
不能被 bits_per_bitset
整除,则会增加浪费的空间。在我的实验中,除了<1024,10>
之外没有进一步的回报,它至少占用32个单词,每个单词32位。
您可以添加一堆其他操作来轻松dynamic_bitset
,包括push_back()
,按位运算符,begin()
/end()
等。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 初始化具有非默认构造函数的std::数组项的更好方法