以特定方式排序数组

时间:2016-04-10 07:54:49

标签: c++ arrays sorting

您好我已尝试在此特殊情况下对数组进行排序

a)可以被3整除的奇数必须先上升

b)即使是可以被3整除的数字也必须最后下降

c)不能被3整除的数字按升序排序

这是我的代码

#include<algorithm>
#include<iostream>
using namespace std ;

bool cmp(int b,int a){

    if((b%2 && b%3==0) && (a%2==0 || a%3 || b>a) )
        return true ;

    if((a%2==0 && a%3==0) && (b%2 || b%3) )
        return true ;

    return false ;
}

int main(){

int ar[8]={18 ,5 ,24 ,9 ,12 ,6 ,2, 3};

sort(ar,ar+8,cmp);

for(int i=0;i<8;i++)
    cout<<ar[i]<<endl ;

return 0;
}

我的输出

9 3 五 2 18 24 12 6

例外

3 9 2 5 24 18 12 6

所以现在数组被分为3个块,但没有按照我上面提到的特殊情况进行排序

4 个答案:

答案 0 :(得分:1)

由于您的比较功能非常复杂,我已经非常详细地重写了它,因此可以单独检查每种可能的情况。我还分成了一个不同的函数,决定每个元素输入的哪个分区。

>>> sentence = "there is an accident along uhuru highway"

>>> a = re.search(r'.* ([\w\s\d\-\_]+) highway', sentence)
>>> print(a.group(1))

>>> uhuru

输出:

#include <algorithm>
#include <iostream>
#include <iterator>

int classify(int const i)
{
    if (i%3==0 && i%2!=0) {
        return 1;
    }
    else if (i%3!=0) {
        return 2;
    }
    else {
        return 3;
    }
}

bool comp(int const a, int const b)
{
    int const a_part = classify(a);
    int const b_part = classify(b);

    if (a_part==1) {
        if (b_part==1) {
            // both in first partition, order ascending
            return a<b;
        }
        else {
            // a in first partition, b not, so a always first
            return true;
        }
    }
    else if (a_part==2) {
        if (b_part==1) {
            // b comes before a
            return false;
        }
        else if (b_part==2) {
            // both in middle partition, order ascendingly
            return a<b;
        }
        else {
            // a in middle partition, b in last partition, so a always first
            return true;
        }
    }
    else { // (a_part==3)
        if (b_part!=3) {
            // a in last partition, b in first or middle partition,
            // so b always comes first
            return false;
        }
        else {
            // both in last partition, order descending
            return b<a;
        }
    }

}

int main()
{
    int ar[8] = {18 ,5 ,24 ,9 ,12 ,6 ,2, 3};
    std::sort(std::begin(ar),
              std::end(ar),
              comp);
    std::copy(std::begin(ar),
              std::end(ar),
              std::ostream_iterator<int>(std::cout,
                                         "\n"));
}

请记住,你的比较器必须引出一个Strict Weak Ordering,我认为这样做,但它比通常用于排序的技术要复杂一些。

始终尽可能将代码编写为 ,而不是简短。如果您有一些复杂的逻辑,请将其拆分,将零件移到函数中,并添加大量注释。请记住,其他人必须阅读并理解它,包括6个月内的自己。

可能更好的方法是拆分排序。你真的在谈论将数组拆分为3个分区,每个分区的处理方式不同。因此,使用std::partition两次,std::sort三次。我认为这可能更容易理解。此代码具有与上述完全相同的输出:

$ ./SO 
3
9
2
5
24
18
12
6

另外值得一提的是,很多人(包括我自己)认为using namespace std;std::endl都是不良做法。

答案 1 :(得分:1)

首先使用std::partition&#34;拆分&#34;将您的数组分成三个分区,然后对每个分区进行排序,您将获得类似

的内容
#include <iostream>
#include <array>
#include <algorithm>
#include <functional>

int main()
{
    std::array<int, 8> array = {{ 18 ,5 ,24 ,9 ,12 ,6 ,2, 3 }};

    std::cout << "Before first partitioning: ";
    for (auto const value : array)
        std::cout << value << ' ';
    std::cout << '\n';

    // First partition putting all odd number even divisible by three first
    auto second_start = std::partition(std::begin(array), std::end(array), [](int const& value) {
        return (value % 2 != 0 && value % 3 == 0);
    });

    std::cout << "Before second partitioning: ";
    for (auto const value : array)
        std::cout << value << ' ';
    std::cout << '\n';

    // Then partition putting all even number even divisible by three first
    auto third_start = std::partition(second_start, std::end(array), [](int const& value) {
        return !(value % 2 == 0 && value % 3 == 0);
    });

    std::cout << "Before sorting: ";
    for (auto const value : array)
        std::cout << value << ' ';
    std::cout << '\n';

    std::sort(std::begin(array), second_start, std::less<int>());
    std::sort(second_start, third_start, std::less<int>());
    std::sort(third_start, std::end(array), std::greater<int>());

    std::cout << "After sorting: ";
    for (auto const value : array)
        std::cout << value << ' ';
    std::cout << '\n';
}

输出

Before first partitioning: 18 5 24 9 12 6 2 3 
Before second partitioning: 3 9 24 5 12 6 2 18 
Before sorting: 3 9 2 5 12 6 24 18 
After sorting: 3 9 2 5 24 18 12 6 

分娩后的输出与您的预期一致。

在&#34;操作&#34;。

中查看here

这是更多的工作,但也保证按预期行事。

答案 2 :(得分:1)

这个简单的比较功能对我有用:

bool cmp(int lhs, int rhs){
    bool lhs_div_3 = lhs % 3 == 0;
    bool rhs_div_3 = rhs % 3 == 0;
    bool lhs_odd = lhs & 1;
    bool rhs_odd = rhs & 1;

    if (lhs_div_3 && lhs_odd) // lhs in class a)
        if (rhs_div_3 && rhs_odd)
            return lhs < rhs;
        else 
            return true;

    if (!lhs_div_3) // lhs in class c)
        if (!rhs_div_3)
            return lhs < rhs;
        else
            return !rhs_odd;

    // else lhs in class b) 
    if (rhs_div_3 && !rhs_odd)
        return rhs < lhs;

    return false;
}

但是如果您有大型阵列并且关心性能,您应该首先对数据进行分区,然后按照其他人的建议对每个3个部分进行独立排序(以避免这种复杂的,即慢速比较功能)。

答案 3 :(得分:1)

我会为{partition1, partition2, order}构建一个元组:

auto helper(int i)
{
    bool isEven = i % 2 == 0;
    bool isMul3 = i % 3 == 0;
    return std::make_tuple(!(!isEven && isMul3), // partition 1
                           isEven && isMul3,     // partition2
                           isEven && isMul3 ? -i : i); // order
}

bool cmp(int lhs, int rhs){
    return helper(lhs) < helper(rhs);
}

Demo

相关问题