У меня есть класс A
и <
компаратор. Как я могу использовать их для сортировки массива A
в нисходящий порядок?
class A {
...
};
class LessA {
bool operator()(const A& a1, const A& a2) const {
...
}
}
vector<A> v;
sort(v.begin(), v.end(), ???);
Я полагаю, я должен заменить ???
с чем-то основанным на LessA
, но я не могу понять, что должно идти туда. Я думал об использовании лямбда-функции, но я искал что-то более короткое.
Если вы хотите отсортировать в соответствии с отношением, определенным вашим LessA
компаратор, просто передать экземпляр LessA
в качестве третьего аргумента (и, поскольку вы используете C ++ 11, предпочитаете глобальный std::begin()
а также std::end()
функции):
std::sort(std::begin(a), std::end(a), LessA());
// ^^^^^^^
Теперь, если ваш LessA()
выражает <
отношение и вы хотите отсортировать по противоположному критерию, вы можете сделать:
std::sort(std::begin(a), std::end(a),
[] (A const& a1, A const& a2))
{
return LessA()(a2, a1);
}
Другая вещь, которую вы можете сделать, это позволить вашему пользовательскому компаратору принять аргумент, который определяет, как он должен выполнять сравнение:
class CompA {
bool lessThan;
public:
CompA(bool lessThan) : _lessThan(lessThan) { }
bool operator()(const A& a1, const A& a2) const {
if (_lessThan)
{
// return true iff a1 < a2;
}
else
{
// return true iff a1 > a2;
}
}
};
Затем вы можете использовать его для сортировки в порядке возрастания:
std::sort(std::begin(a), std::end(a), CompA(true));
И этот способ сортировки в порядке убывания:
std::sort(std::begin(a), std::end(a), CompA(false));
Еще одна возможность, учитывая ваш оригинал LessA
компаратор, это использовать std::bind
поменять местами порядок аргументов с вашим пользовательским компаратором:
LessA comp;
using namespace std::placeholders;
std::sort(std::begin(v), std::end(v),
std::bind(&LessA::operator(), comp, _2, _1));
Сортировка диапазона в обратном направлении:
vector<A> v;
sort(v.rbegin(), v.rend(), LessA());
rbegin
, а также rend
дать вам обратные итераторы.
Инкапсулируйте, если это слишком запутанно:
void reverse_sort(vector<A>& v) {
sort(v.rbegin(), v.rend(), LessA());
}
Использование:
vector<A> v;
reverse_sort(v);
использование std::greater
для функтора сравнения. По умолчанию (std::less
) даст вам восходящий порядок; это даст вам нисходящий порядок. (Вам нужно будет добавить using namespace std::rel_ops;
(ссылка на сайт) заявление или явное определение operator>
также.)
Взято из cppreference.com
#include <algorithm>
#include <functional>
#include <array>
#include <iostream>
int main()
{
std::array<int, 10> s = {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
// sort using the default operator<
std::sort(s.begin(), s.end());
for (int a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// sort using a standard library compare function
std::sort(s.begin(), s.end(), std::greater<int>());
for (int a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// sort using a custom functor
struct {
bool operator()(int a, int b)
{
return a < b;
}
} customLess;
std::sort(s.begin(), s.end(), customLess);
for (int a : s) {
std::cout << a << " ";
}
std::cout << '\n';
// sort using a lambda
std::sort(s.begin(), s.end(), [](int a, int b) {
return b < a;
});
for (int a : s) {
std::cout << a << " ";
}
std::cout << '\n';
}
Учитывая функцию lt(a, b)
который реализует a<b
, вы можете создать функцию, которая реализует a>=b
вернувшись !lt(a, b)
, Реализовать >
нужно вернуть !lt(b, a) && !(lt(a,b) || lt(b,a))
,
lt(a, b) || lt(b, a)
эквивалентно a!=b
так что вышеупомянутое эквивалентно a>=b && a!=b
который сводится к a>b
,
Тем не менее, вы можете сойти с рук просто std::not2(LessA())
, Это будет сортировать с >=
который будет сортировать в порядке убывания.
Сделать ()
оператор LessA
возвращение класса !(a1 < a2)
и передать это так:
std::sort(v.begin(), v.end(), LessA());