std::partition 原地二分划分,满足谓词的元素移至前段、不满足的移至后段,不保证组内顺序;返回分界迭代器,要求双向迭代器、无异常谓词且不可修改容器。
它把满足谓词的元素移到前面,不满足的移到后面,但同一组内的原始顺序不保留。这和 std::stable_partition 有本质区别——后者保序,但性能略差。
常见误用是以为它像 std::sort 那样“整理”数据,其实它只做二分划分,不排序也不稳定。
std::vector、std::list 可用;std::forward_list 不行)bool,不能修改元素本身以 std::vector 划分正负数为例:
std::vectorv = {-2, 3, -1, 4, 0, -5}; auto pivot = std::partition(v.begin(), v.end(), [](int x) { return x > 0; });
执行后 v 可能变为 {3, 4, -2, -1, 0, -5}(正数在前,但 3 和 4 的相对位置可能交换),pivot 指向 -2。
end() 作起始,也不可越界)std::partition 直接返回 begin(),不报错std::partition_copy 不修改原容器,而是把满足/不满足的元素分别拷贝到两个目标区间。适合“只读划分 + 分别处理”场景。
例如需要同时统计奇偶数量又保留原数组:
std::vectorsrc = {1, 2, 3, 4, 5}; std::vector odds, evens; s td::partition_copy(src.begin(), src.end(), std::back_inserter(odds), std::back_inserter(evens), [](int x) { return x % 2 != 0; });
std::partition:就地、快(O(n) 时间,O(1) 额外空间)、不保序std::partition_copy:非破坏性、需双倍空间、同样不保序,但避免副作用若谓词里捕获了容器引用并试图修改它,会导致未定义行为。例如:
std::vectordata = {1,2,3}; std::partition(data.begin(), data.end(), [&data](int x) { data.push_back(x * 2); // ❌ 危险!可能使迭代器失效 return x > 1; });
std::vector 使用时,确保容量足够,避免内部 realloc 导致迭代器全废实际项目中,最常被忽略的是:划分后没用返回的 pivot 迭代器去切分逻辑,而是重新遍历或硬编码索引,白白浪费了算法提供的分界信息。