c++ - 在 C++ 中以相同的方式同时划分两个范围的元素

标签 c++ algorithm stl

是否有一种 C++ 标准方法可以同时划分两个元素范围并根据第一个元素范围的划分来划分第二个元素范围?与 std::partition 一样,分区对一个元素范围进行操作,而另一范围的元素也以相同的方式进行分区。或者是否有一种有效的方法可以做到这一点,而无需复制和调整 std::partition 方法并且无需压缩两个范围?

示例:

[a, b, c, d, e] -> [a, c, e, b, d]
[f, g, h, i, j] -> [f, h, j, g, i]

最佳答案

虽然我现在没有时间详细编写代码,但我有以下想法。从我在 std::{stable_}partition 的文档中可以看到,它绝不会向客户端报告其执行的交换。因此,您无法提取该信息并将其应用于第二个范围。任何依赖于比较和手动重新排序元素的操作都可能太慢。

方法 1(更简单) 我想到了一种更简单的实现方式。上面我声明我们无法从 std::partition 中获得交换。 。嗯,我认为我们可以,但代价是使用一些额外的内存。

  1. 将前导 vector (一个分区基于一个分区)转换为 std::vector<std::pair<T, int>> .
  2. 一开始,每个标签都等于 vector 中的元素位置。
  3. 调用 std::partition谓词仅考虑 std::pair::first() (即 T )。
  4. 之后std::partition退出时,按如下方式对第二个 vector 重新排序:前导 vector 中的标记值是第二个 vector 中的元素索引,而前导 vector 的元素索引是新的元素位置。因此,新的排序是已知的,我们可以通过巧妙地执行交换来相应地对第二个 vector 重新排序。

此方法需要额外的内存 O(n)乘以sizeof一个int或者说 char对于短输入 vector 。但是,它很容易实现:只有一个自定义谓词和一个交换循环。

方法 2(更复杂)

基于交换从外部不可见的相同假设,我们可以得出如下解决方案:

  1. 将两个范围“粘合”在一起形成一个线性数据结构(可能通过定义代理适配器类)

  2. 启动std::partition对此,使用自定义谓词,它将比较“压缩”DS 中的第一个元素(沿着 pair::first() 的行),但由于两个数组现在通过适配器统一,因此交换将发生在两个数组中的元素

  3. 根据需要移除临时 DS(“取消粘合”两个阵列)

编辑:鉴于 std::partition使用std::swap ,这种方法的关键部分是重新定义 std::swap对于您的配对元素类型(这仍然称为模板的“重载”吗?)。据我所知,这个函数可以为自定义类型重载,这证明可以使用 std::partition 构造像方法 2 中描述的算法。 ,但重新定义交换函数和比较谓词。

关于c++ - 在 C++ 中以相同的方式同时划分两个范围的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35482912/

相关文章:

c++ - 在 C++ 中将对象传递给线程

c++ - 使用 operator<<? 根据某些条件打印不同类型的不同值

algorithm - 使用具有特定运行时间的算法在图中查找三角形

c++ - 为什么 STL 中的 priority_queue 不遵循严格的弱排序?

c++ - 在 Qt 类的 getter 中按值返回

c++ - Win32 - 确定路径是否有可用的巨型图标

c# - 如何计算总数使用 c# 的字符串的可能组合?

java - 在矩阵中寻找路径的深度优先搜索

c++ - 使用相同的 C++ 代码在跨平台之间获取运行时错误

c++ - 了解 std::end() 的行为和 vector 中的内存分配