Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort based on multiple things in C++

Tags:

c++

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

How can I use Quicksort to sort the values into increasing age, with females before males and surnames in alphabetical order? I've got a:

bool CompareData(const int& A, const int& B) {     return Records[A].Age < Records[B].Age; //this sorts by age atm } 
like image 251
Johnny Avatar asked Aug 26 '10 11:08

Johnny


2 Answers

the general pattern is:

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; }  

where < indicates the "less than" in the desired sort order, you might need to use custom comparison operators for that (e.g. strcmp for strings,or reverse the < if you want to order descending) (thanks Harry for pointing this out)

I've used < on all conditions, since that's sometimes the only comparison operation available, e.g. when you have to use an unknown data type's comparison predicate.

[edit] Note: the last line return false handles the case where aand bare considered equal for the comparator.

Imagine a.PrimaryCondition==b.PrimaryCondition and a.SecondaryCondition==b.SecondaryCondition - in this case, none of the previous conditions returns any value.

like image 103
peterchen Avatar answered Oct 19 '22 19:10

peterchen


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)); } 

This compares first by age and returns true if A should appear before B based on age.

If ages are equal, it then compares by gender, and returns true if A should appear before B based on gender (A is female and B is male).

If ages are equal and genders are equal, it then compares by surname (using strcmp, although if you had used std::string instead of a char array, you could have just used <), and returns true if A should appear before B alphabetically by surname.

like image 31
Tyler McHenry Avatar answered Oct 19 '22 19:10

Tyler McHenry