【问题标题】:How can I sort only some parts of the array in a specific order in c++?如何在 C++ 中按特定顺序仅对数组的某些部分进行排序?
【发布时间】:2021-07-16 12:09:56
【问题描述】:

所以假设我有一个数组array{12, 10, 10, 9, 8, 8, 8} 按降序排列。 我想在数组末尾按升序对可以除以 2 但不是 4 的数字进行排序,除以 4 的数字在数组开头按降序排序,其余的在中间(没有具体的顺序)。对于我的示例,转换后它应该如下所示: array{12, 8, 8, 8, 9, 10, 10}。有什么办法可以有效地做到这一点? c++语言。 如有拼写错误,请见谅。

【问题讨论】:

  • 使用 std::sort 并提供一个 predicate 比较 lambda 来编码您的订购标准。
  • 听起来像是 std::sortstd::partition 的工作
  • @NathanOliver 我查了 std::partition 但我不明白它应该做什么。
  • 它允许您根据某些谓词对数据集进行分区。它会将谓词为真的所有元素移动到数组的前面,并将其余元素留在最后。您可以对数组的前面部分进行排序以获得您想要的顺序。
  • @AdrianHEY std::partition 用于将您的容器一分为二。容器的一侧保存满足特定条件的元素,另一侧保存不满足特定条件的元素。看起来您想先对容器进行两次分区,因为您需要 3 个部分。容器正确分区后,您可以根据分区的要求单独对每个分区进行排序。

标签: c++ arrays sorting


【解决方案1】:

让我们组织需求。

要求的顺序是:

  1. 除以 4 的数字
  2. 其他
  3. 可以被 2 整除但不能被 4 整除的数

按照上述规则,在优先级相同的号码中,号码应该是

  1. 降序
  2. 无特定顺序
  3. 升序

让我们实现这个:

#include <iostream>
#include <vector>
#include <algorithm>

void test(std::vector<int> array) { // intensionally passed by value
    std::cout << "before sorting:";
    for (int v : array) std::cout << ' ' << v;
    std::cout << '\n';

    std::sort(array.begin(), array.end(), [](int a, int b) -> bool {
        int pa, pb; // priority a/b

        if (a % 4 == 0) pa = 1;
        else if (a % 2 == 0) pa = 3;
        else pa = 2;

        if (b % 4 == 0) pb = 1;
        else if (b % 2 == 0) pb = 3;
        else pb = 2;

        // if the priority differs, sort according to the priority
        if (pa != pb) return pa < pb;
        // if both can be divided by 4, sort in descending order
        if (pa == 1) return b < a;
        // if both can be divided by 2 but not with 4, sort in ascending order
        if (pa == 3) return a < b;
        // no specific order for the rest
        return false;
    });

    std::cout << "after  sorting:";
    for (int v : array) std::cout << ' ' << v;
    std::cout << '\n';
}

int main(void) {
    std::vector<int> array = {12, 10, 10, 9, 8, 8, 8};
    std::vector<int> array2 = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    test(array);
    std::cout << '\n';
    test(array2);
    return 0;
}

Example output:

before sorting: 12 10 10 9 8 8 8
after  sorting: 12 8 8 8 9 10 10

before sorting: 10 9 8 7 6 5 4 3 2 1
after  sorting: 8 4 9 7 5 3 1 2 6 10

【讨论】:

  • 成功了!非常感谢您的回答。只有一件事.. arra.begin()、array.end() 之后的 std::sort 中有什么?还有小箭头->。以前从未听说过这些
  • 整个[](int a, int b) -&gt; bool { ... }是一个lambda expression
【解决方案2】:

作为MikeCAT's fine answer 的替代方案,C++20 添加了sort 的变体,它接受投影,即在我们将其传递给比较函子之前应用于每个元素的函数.

这利用了std::tuple 具有预定义的&lt; 的事实,该&lt; 依次按每个成员对元组进行排序。

#include <iostream>
#include <vector>
#include <algorithm>

std::tuple<int, int> my_order(int val) {
    if (val % 4 == 0) return { 1, -val };
    else if (val % 2 == 0) return { 3, val };
    else return { 2, 0 };
}

void test(std::vector<int> array) { // intensionally passed by value
    std::cout << "before sorting:";
    for (int v : array) std::cout << ' ' << v;
    std::cout << '\n';

    std::ranges::sort(array.begin(), array.end(), std::ranges::less{}, my_order);

    std::cout << "after  sorting:";
    for (int v : array) std::cout << ' ' << v;
    std::cout << '\n';
}

int main(void) {
    std::vector<int> array = {12, 10, 10, 9, 8, 8, 8};
    std::vector<int> array2 = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
    test(array);
    std::cout << '\n';
    test(array2);
    return 0;
}

【讨论】:

    猜你喜欢
    • 2021-02-10
    • 1970-01-01
    • 2010-09-26
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 2021-09-10
    • 2020-06-03
    相关资源
    最近更新 更多