【问题标题】:Sorting array of objects in c++, repeating values [duplicate]在c ++中对对象数组进行排序,重复值[重复]
【发布时间】:2021-12-03 04:51:48
【问题描述】:

我目前正在尝试对一组对象进行排序。排序函数工作正常,但如果像 age 这样的值重复,我想根据 height 对它们进行排序,如果 height 重复我想按 weight 对它们进行排序。顺序基于用户输入。

我想让程序尽可能快地运行,同时尽可能少地使用内存。这就是我发布这个问题的原因,只是为了确保找到最佳解决方案。

我被困住了。我不知道如何在这个数组中获取重复值并同时在不同条件下对它们进行排序,而不是对所有对象进行排序。

这是代码:

#include <iostream>
using namespace std;

class Person{
public:
    string name;
    int age;
    int weight;
    int height;
};
    
void sortByAge(int n, Person * array);
void sortByHeight(int n, Person * array);
void sortByWeight(int n, Person * array);
    
int main()
{
    int n;
    cin >> n;

    Person * people = new Person[n];

    for(int i = 0; i < n; i++) {
        cin >> people[i].name >> people[i].age >> people[i].weight >> people[i].height;
    }
    cout << endl << endl;

    int firstOrder, secondOrder, thirdOrder;
    cout << "Enter the order of sorting, choose numbers form 1 to 3, where 1 is sorting by Age, 2 is sorting by Height and 3 is sorting by weight \n";
    cin >> firstOrder >> secondOrder >> thirdOrder;

    if(firstOrder == 1) {
        sortByAge(n,people);
        if(secondOrder == 2) {
            sortByHeight(n,people);
            sortByWeight(n,people);
        } else if(secondOrder == 3) {
            sortByWeight(n,people);
            sortByHeight(n,people);
        }
    } else if(firstOrder == 2) {
        sortByHeight(n,people);
        if(secondOrder == 1) {
            sortByAge(n,people);
            sortByWeight(n,people);
        } else if(secondOrder == 3) {
            sortByWeight(n,people);
            sortByAge(n,people);
        }
    } else if(firstOrder == 3) {
        sortByWeight(n,people);
        if(secondOrder == 1) {
            sortByAge(n,people);
            sortByHeight(n,people);
        } else if (secondOrder == 2) {
            sortByHeight(n,people);
            sortByAge(n,people);
        }
    }
    delete [] people;
    return 0;
}

void sortByAge(int n, Person * array) {
    int y = 0;
    Person x;
    for(int i = 1; i < n; i++) {
        x = array[i];
        y = i - 1;
        while(y >= 0 && array[y].age < x.age) {
            array[y+1] = array[y];
            y--;
        }
        array[y+1] = x;
    }
}

void sortByWeight(int n, Person * array) {
    int y = 0;
    Person x;
    for(int i = 1; i < n; i++) {
        x = array[i];
        y = i - 1;
        while(y >= 0 && array[y].weight < x.weight) {
            array[y+1] = array[y];
            y--;
        }
        array[y+1] = x;
    }
}

void sortByHeight(int n, Person * array) {
    int y = 0;
    Person x;
    for(int i = 1; i < n; i++) {
        x = array[i];
        y = i - 1;
        while(y >= 0 && array[y].height < x.height) {
            array[y+1] = array[y];
            y--;
        }
        array[y+1] = x;
    }
}

【问题讨论】:

  • 如果你想按多个条件排序,那么实际进行排序的代码需要使用这些多个条件。
  • 一个接一个地调用排序函数不会给你想要的结果。那只会打乱数组。您最终得到的唯一结果是最后一个调用函数的输出。您需要在单个函数内进行所有比较。传入参数来控制这些比较。考虑使用std::sort(),而不是编写自己的排序逻辑。

标签: c++ algorithm sorting c++11


【解决方案1】:

我建议使用std::tie 来简化多个字段的排序。

例子:

#include <algorithm>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>

class Person{
public:
    std::string name;
    int age;
    int weight;
    int height;
};

// A comparison function taking member pointers as template parameters
// and using std::tie to compare two Persons.
template<auto... S>
bool compfunc(const Person& lhs, const Person& rhs) {
    return std::tie((lhs.*S)...) < std::tie((rhs.*S)...);
}

int main() {
    std::vector<Person> persons {
        {"foo", 10, 10, 10},
        {"foo", 9, 10, 10},
        {"foo", 10, 9, 10},
        {"foo", 10, 10, 9},
        {"bar", 11, 12, 13},
    };

    // Supply the sort order as template parameters where the first parameter
    // has the highest priority.
    std::sort(persons.begin(), persons.end(), compfunc<&Person::name,
                                                       &Person::age,
                                                       &Person::weight,
                                                       &Person::height>);

    for(auto&[n,a,w,h] : persons) {
        std::cout << n << ' ' << a << ' ' << w << ' ' << h << '\n';
    }
}

输出:

bar 11 12 13
foo 9 10 10
foo 10 9 10
foo 10 10 9
foo 10 10 10

【讨论】:

  • 我喜欢这种模式。我想 - 用可变属性列表概括它 - 通过提取 as_tied&lt;S1, ...&gt;(T&amp;&amp;) 辅助函数来简化它
  • @xtofl 谢谢!是的,在这种情况下会更可取,但我认为这并不容易。 boost 中可能有一些辅助函数可以实现这一点。 ...或者你的意思是我刚刚在编辑中做到了?
  • 部分是的。当我指的是参数包时,我不知道为什么我写了“属性列表”。
  • @xtofl 好的。我正在考虑如何在运行时灵活地构建成员变量指针包,这样就不需要写出所有可能的组合。我发现这很难。我想我已经看到了一些可能有助于提升的东西。 Boost PFR
猜你喜欢
  • 1970-01-01
  • 2014-08-04
  • 2014-05-29
  • 2012-02-28
  • 2023-03-26
  • 2013-07-26
  • 2012-10-22
  • 2017-04-27
  • 2014-08-25
相关资源
最近更新 更多