基于C++中的多个事物进行排序

Joh*_*nny 17 c++

struct Record
{
    char Surname[20];
    char Initial;
    unsigned short int Gender; //0 = male | 1 = female
    unsigned short int Age;
};
Record X[100];
Run Code Online (Sandbox Code Playgroud)

我如何使用Quicksort将值排序为年龄增长,男性和姓氏之前的女性按字母顺序排列?我有一个:

bool CompareData(const int& A, const int& B)
{
    return Records[A].Age < Records[B].Age; //this sorts by age atm
}
Run Code Online (Sandbox Code Playgroud)

pet*_*hen 35

一般模式是:

bool CompareData(const T& a, const T& b) 
{ 
   if (a.PrimaryCondition < b.PrimaryCondition) return true;
   if (b.PrimaryCondition < a.PrimaryCondition) return false;

   // a=b for primary condition, go to secondary
   if (a.SecondaryCondition < b.SecondaryCondition) return true;
   if (b.SecondaryCondition < a.SecondaryCondition) return false;

   // ...

   return false;
} 
Run Code Online (Sandbox Code Playgroud)

where <表示所需排序顺序中的"小于",您可能需要使用自定义比较运算符(例如,strcmp对于字符串,或者<如果您想要降序则反转)(感谢Harry指出这一点)

我已经<在所有条件下使用过,因为这有时是唯一可用的比较操作,例如,当你必须使用未知数据类型的比较谓词时.

[编辑]注意:最后一行return false处理比较器的情况ab被认为是相等的情况.

想象一下,a.PrimaryCondition==b.PrimaryConditiona.SecondaryCondition==b.SecondaryCondition-在这种情况下,没有条件的已返回的任何值.

  • @gustafbstrom:当且仅当“ a &lt;b”时,sorts的谓词才需要返回“ true”,即对于“ a == b”而言,为“ false”。有关详细信息,请参见此处:http://en.cppreference.com/w/cpp/concept/Compare ---在此处返回“ true”会*使您的结果混乱。只需考虑:是否相等的检验是`!(a &lt;b)&amp;&amp;!(b &lt;a)`。您的“ return true”将无法通过该测试。 (3认同)
  • @Tyler:如果你想颠倒顺序,你交换`return true;`和`return false;`你不要开始使用`operator&gt;`,因为正如peterchen所说,C++标准算法库建立的做法是排序由 `&lt;` 定义,并且只有 `&lt;`。 (2认同)

Tyl*_*nry 25

bool CompareData(const int& A, const int& B)
{
    return (Records[A].Age < Records[B].Age) ||
           ((Records[A].Age == Records[B].Age) && (Records[A].Gender > Records[B].Gender)) || 
           ((Records[A].Age == Records[B].Age) && (Records[A].Gender == Records[B].Gender) &&
              (strcmp(Records[A].Surname, Records[B].Surname) < 0));
}
Run Code Online (Sandbox Code Playgroud)

这首先按年龄进行比较,如果A应该根据年龄出现在B之前,则返回true.

如果年龄相等,则按性别进行比较,如果A应基于性别出现在B之前,则返回true(A为女性,B为男性).

如果年龄相等且性别相等,则按姓氏进行比较(使用strcmp,尽管如果您使用过std::string而不是char数组,则可能刚刚使用过<),如果A应按字母顺序出现在B之前,则返回true.


jk.*_*jk. 16

所有唱歌所有跳舞比较器的另一个选择是确保你的排序是稳定的排序(快速排序不一定稳定)并且每次使用不同的比较器进行多次排序.

例如

bool CompareAge (const record& l, const record& r)
{
  return l.age < r.age;
}

bool CompareGender (const record& l, const record& r)
{
  return l.gender < r.gender;
}

std::stable_sort(X, X+100, &CompareGender);
std::stable_sort(X, X+100, &CompareAge);
Run Code Online (Sandbox Code Playgroud)

这可能会稍微慢一些,但允许您按顺序排列更灵活

  • 这是最好的答案. (6认同)
  • 根据实施情况的答案根本不是一个好的答案.;) (3认同)
  • 但Quicksort*不稳定.(编辑后)正如我所说,`std :: sort`不稳定; 你应该使用`std :: stable_sort`代替. (2认同)

MSa*_*ers 6

简单的C++解决方案是

struct Record {
    std::string Surname;
    char Initial;
    unsigned short int Gender; //0 = male | 1 = female
    unsigned short int Age;

    operator<(Record const& rhs) const {
        return std::tie(Gender, Age, Surname) < std::tie(rhs.Gender, rhs.Age, rhs.Surname);
};
Run Code Online (Sandbox Code Playgroud)

但是,std::tie直接对字段值进行排序.这意味着你不能使用char[20],男性会先排序.一个简单的变化解决了这个:

struct Record {
    char Surname[20];
    char Initial;
    unsigned short int Gender; //0 = male | 1 = female
    unsigned short int Age;

    operator<(Record const& rhs) const {
        return std::make_tuple(~Gender, Age, std::string(Surname)) <
               std::make_tuple(~rhs.Gender, rhs.Age, std::string(rhs.Surname));
};
Run Code Online (Sandbox Code Playgroud)

随着make_tuple我们可以通过表情.


Arc*_*hie 5

最好像这样实现比较器:

bool CompareRecords(const Record& a, const Record& b)
{
    if (a.Age < b.Age)
        return true;
    else if (a.Age > b.Age)
        return false;

    if (a.Gender < b.Gender)
        return true;
    else if (a.Gender > b.Gender)
        return false;

    if (strcmp(a.Surname, b.Surname) < 0)
        return true;

    return false;
}
Run Code Online (Sandbox Code Playgroud)

这使您可以轻松使用std::sort算法.排序本身将如下所示:

std::sort(X, X + 100, &CompareRecords);
Run Code Online (Sandbox Code Playgroud)

编辑

您甚至可能想要实现operator <此结构 - 在这种情况下,您通常可以将两个Record结构对象与运算符进行比较<.然后你不需要添加第三个参数std::sort.好吧,有了这个并实施,operator ==你可以做所有可能的比较.:)