C++:结构体和函数在元素排序方面的区别

6

我有一个包含两个字段的struct

struct road {
    int from, len ;
};

由于某些原因,我需要按照以下方式对我的road进行排序:

  • 在数组中按升序from排序

  • 在优先队列中按升序len排序

因此,我已经包含了以下内容:

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

我遇到过一些建议重载 operator< 的网站,但是由于有两种可能的排序方式,这个方法感觉不太对,而且只能解决其中的一个。

通过查阅教材并进行试验,我终于让它工作了:

bool cmpFrom (const road & a, const road & b) {
    return (a.from < b.from) ;
}

struct cmpLen {
    bool operator () (const road & a, const road & b){
        return (a.len < b.len) ;
    }
};

适用于:

std::sort(trips, trips + nbRoads, &cmpFrom) ;
std::priority_queue<road, std::vector<road>, cmpLen> pickRoad ;

这里的trips当然是一个road []

它编译通过了(虽然我没有尝试运行它,但应该没问题),但是定义两个非常相似的比较器方式有些奇怪,所以有没有一种方法可以以相同的方式定义两个比较方法呢?

cmpFrom的定义更改为

struct cmpFrom {
    bool operator () (const road & a, const road & b){
        return (a.from < b.from) ;
    }
};

提供
chantier.cpp: In function ‘int main()’:
chantier.cpp:38:48: error: expected primary-expression before ‘)’ token
     std::sort(trips, trips + nbRoads, &cmpFrom) ;

我猜这意味着“当我期望一个引用时,你给了我一个类型”。在写作时。
bool cmpLen (const road & a, const road & b) {
    return (a.len <= b.len) ;
}

提供
chantier.cpp: In function ‘int main()’:
chantier.cpp:52:56: error: type/value mismatch at argument 3 in template parameter list for ‘template<class _Tp, class _Sequence, class _Compare> class std::priority_queue’
     std::priority_queue<road, std::vector<road>, cmpLen> pickRoad ;
                                                        ^
chantier.cpp:52:56: note:   expected a type, got ‘cmpLen’
chantier.cpp:56:30: error: request for member ‘top’ in ‘pickRoad’, which is of non-class type ‘int’
...

是否有一种方法可以使这些比较方法适用于两个容器?或者是否有第三种方法可以同时适用于两个容器?

如果我需要在两个容器中使用相同的排序,那么是否需要定义两次相同的比较方法,但其中一个在struct内部?


什么是问题?啊啊......您已经编辑了问题以表达您正在批准的答案。请不要这样做。只需在对您有帮助的答案旁边打勾即可。 - Marek R
3个回答

5

把它们都定义为结构体会更容易,因为你总是可以从类型创建一个对象,并使其按预期工作,但从函数获取一个类型并使其充当函数的调用方要困难得多。

实际上,您几乎已经完成了struct cmpFrom。然而,您正确地指出了std::sort需要一个比较器对象(如函数),而不是一个类型。当然,在cmpFrom是一种类型时,进行&cmpFrom操作是无效的C ++。相反,您需要创建该类型的对象;由于定义了operator(),该对象将是可调用的,并且执行您想要的操作。所以只需这样调用std::sort

std::sort(trips, trips + nbRoads, cmpFrom{});

5
你几乎做到了。在 std::sort 中,你需要一个对象,该对象可以调用 operator()
bool cmpFrom (const road & a, const road & b) {
    return (a.from < b.from) ;
}
std::sort(trips, trips + nbRoads, &cmpFrom);

函数指针可以像函数一样使用,因此代码有效。 当您将cmpFrom更改为

struct cmpFrom {
    bool operator () (const road & a, const road & b){
        return (a.from < b.from) ;
    }
};

你不能再使用std :: sort(trips,trips + nbRoads,&cmpFrom);,因为您无法将&应用于类型名称。相反,您需要获取cmpFrom的对象,您可以通过以下方式实现:

std::sort(trips, trips + nbRoads, cmpFrom{});

现在,priority_queuesort都可以使用cmpFrom了。


3
std::sort(v.begin(), v.end(), [](const auto& a, const auto& b){ return a > b; });

std::sort函数和std::priority_queue类模板需要两个不同的东西: sort需要一个可调用对象,而priority_queue模板需要一种类型,该类型允许创建对象。

因此,sortpriority_queue更全面 - 您可以将其与函数或函数对象一起使用。您唯一需要做的就是提供一个真正的对象(而当前在您的代码中,您正在尝试获取一个类型的地址,这是无意义的)。

为了在您的示例中修复它,只需将代码更改为

std::sort(v.begin(), v.end(), [](const auto& a, const auto& b){ return a > b; });
std::sort(trips, trips + nbRoads, cmpFrom{});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接