首页 > 解决方案 > 通过元素原始位置的奇偶校验来稳定分区 std::vector

问题描述

我想std::vector通过容器中元素原始索引的奇偶校验来划分 a 。换句话说,我想把它分成两半:第一部分包含所有偶数索引元素,第二部分包含所有奇数索引元素。

元素之间的排序关系无关紧要,重要的是原始向量中的位置。

我想用标准算法和 lambdas 来实现这种效果,最好是在原地。我可以通过常规for循环来做到这一点。

例子

让我们假设我们有一个元素向量a b c d e f。所需的分区是a c e b d f. 第一个 ( a)、第三个 ( c) 和第五个 ( e) 元素被移动到前面,而第二个 ( b)、第四个 ( d) 和第六个 ( f) 元素被移动到后面。

我的尝试

我有一个类似于这个的对象:

struct T {
    int x;
};

我能够通过这样的字段值对其进行分区:

std::vector<T> ts {{1}, {2}, {4}, {3}, {6}, {5}};
auto predicate = [](const T& t) {
    return t.x % 2 == 1;
};
std::stable_partition(ts.begin(), ts.end(), predicate);

结果是1 3 5 2 4 6。我希望分区返回1 4 6 2 3 5

我试图定义predicate

auto predicate = [](const std::vector<T>::const_iterator& t)
    return t->x % 2 == 1;
};

但它不能编译,而且显然没有任何意义。

为了说明我的问题,我编写了一个for执行此分区的循环,尽管不是以稳定的方式。

for (auto i = ts.begin() + 1, j = ts.begin() + 2; j != ts.end(); i += 1, j += 2) {
    std::swap(*i, *j);
}

概括

是否可以通过算法实现它std,还是我需要求助于标准循环?

标签: c++algorithmfunctional-programmingstd

解决方案


在 c++11 中,使用计数器作为索引来验证它是偶数还是奇数。

#include <iostream>
#include <vector>

struct T {
    int x;
};

int main()
{
    std::vector<T> ts {{1}, {2}, {4}, {3}, {6}, {5}};
    int counter =0;
    auto predicate = [&counter]() {
        ++counter;
        return (counter % 2 == 1);
    };
    std::stable_partition(ts.begin(), ts.end(), predicate);

    for(auto i: ts)
        std::cout << i.x << ", ";

}

推荐阅读