C++如何实现高效的位集排序

雨晨大大_7769

雨晨大大_7769

2026-06-02

233人浏览

原创

位集排序本质是计数排序,即提取所有置位索引并升序排列;高效方法包括使用_find_first/_find_next(gcc/clang)或分块+popcount(跨平台)。

c++如何实现高效的位集排序

位集排序本质是计数排序,不是传统比较排序

位集(std::bitset)本身不支持“排序”——它没有顺序概念,只有固定位置的 0/1。所谓“位集排序”,实际是指:把一个位集里所有置位(1)的位置按升序提取出来,形成有序索引序列。这本质上是遍历 + 收集,不是 std::sort 能直接作用的对象。

常见错误是试图对 std::bitset 对象调用 std::sort,结果编译失败或行为未定义;也有人误用 bitset::to_string() 再转数组排序,白白引入字符串开销和内存拷贝。

  • 真正高效的做法是利用位集的稀疏性或稠密性选择不同策略
  • 若已知置位数量极少(比如 bitset::_Find_first() 和 _Find_next()(GCC/Clang 扩展)最省时
  • 若位集很大但置位较密集(比如 >1%),直接遍历 test(i) 并 push_back 索引更稳定、可移植

用 _Find_first() / _Find_next() 快速提取置位索引(GCC/Clang)

这两个非标准但广泛支持的成员函数专为高效扫描设计,时间复杂度接近 O(置位数),而非 O(总位数)。它们跳过连续 0 段,底层常调用 bsf/tzcnt 指令。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
std::bitset bs;
bs.set(42);
bs.set(123);
bs.set(999);

std::vector<size_t> indices;
size_t pos = bs._Find_first();
while (pos != bs.size()) {
    indices.push_back(pos);
    pos = bs._Find_next(pos);
}
// indices == {42, 123, 999}
</size_t>
  • 注意:_Find_first() 返回 size() 表示无置位,不是 npos
  • MSVC 不支持这些函数;跨平台项目需 #ifdef 或改用可移植方案
  • 不要在循环中反复调用 bs.test(i) 配合 i++ —— 这会退化为全量扫描

可移植方案:分块扫描 + 内置 popcount 加速

对需要兼容 MSVC 或嵌入式环境的场景,手动分块(如每 64 位一块)+ std::popcount(C++20)能兼顾效率与可读性。先判断每块是否全零,再逐位检查非空块。

std::vector<size_t> extract_set_bits(const std::bitset& bs) {
    std::vector<size_t> res;
    res.reserve(bs.count()); // 预分配避免多次 realloc
    for (size_t i = 0; i 
<ul>
<li>虽然看起来是 O(N),但现代 CPU 分支预测对 <code>test()</code> 很友好,且 <code>reserve()</code> 减少内存抖动</li>
<li>C++20 起可用 <code>std::popcount(bs.to_ullong() & mask)</code> 做块级预判,但 <code>bitset::to_ullong()</code> 仅支持 ≤64 位,大位集需手写分块逻辑</li>
<li>别用 <code>to_string()</code> → <code>find('1')</code>,字符串构造开销远超位操作本身</li>
</ul>
<h3>为什么不用 <code>std::sort</code> 对索引数组二次排序?</h3>
<p>因为根本不需要——位集的索引天然满足“位置即顺序”,你收集的索引本身就是升序的(只要按 i 从 0 到 size()-1 扫描)。唯一例外是用 <code>_Find_next()</code> 时,它返回的索引严格递增,也无需再排。</p>
<ul>
<li>如果意外得到乱序结果,说明扫描逻辑写错了(比如用了随机迭代器或误读了位序)</li>
<li>某些人把多个位集 or 后再提取,误以为要重排序,其实 or 结果仍是单一位集,索引仍天然有序</li>
<li>性能敏感场景下,额外调用 <code>std::sort</code> 对已有序数组是纯浪费,还可能触发 introsort 的 pivot 判断开销</li>
</ul>
<p>位集“排序”的关键,在于别把它当成待排序容器,而要意识到你只是在做一次有结构的索引枚举——路径选对了,效率自然上来。最容易被忽略的是:没提前 <code>reserve()</code> 导致 vector 多次扩容,或者在 MSVC 上盲目依赖 <code>_Find_next()</code> 编译不过。</p></size_t></size_t>

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2248

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1019

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

426

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

580

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1409

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1217

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习