Сортировка только с использованием оператора less-than по сравнению с функцией trivalue compare
В C++/STL сортировка выполняется с использованием только оператора less-than. Хотя я понятия не имею, как алгоритмы сортировки фактически реализованы, я предполагаю, что другие операции создаются implicite:
a > b *equals* b < a == true
a == b *equals* !(a < b) && !(b < a)
по сравнению с использованием функции trivalue* compare, например Java, это хорошо для производительности, или почему было принято это дизайнерское решение?
мое предположение заключается в том, что любую функцию сравнениедля trivalue еще предстоит реализовать эти comparissons в сам, в результате того же представления.
* * по trivalue функции сравнения, я имею в виду функцию сравнения, которая возвращает -1, 0 и 1 меньше, равно и выше, чем*
обновление:
Кажется, космический корабль <=>
оператор приходит в C++20, поэтому, очевидно, комитет думал, что есть недостатки использования только operator<
.
3 ответов
в некотором смысле два других неявны, но более точным было бы сказать, что сортировка сравнения на самом деле не нужно трехзначный компаратор и сорта C++реализованы таким образом, что не используют его для минимизации поведения, требуемого от компаратора.
было бы неправильно для std:: sort определять и исключительно использовать что-то вроде этого:
template <typename T, typename Cmp>
int get_tri_value(const T &a, const T &b, Cmp lessthan) {
if (lessthan(a,b)) return -1;
if (lessthan(b,a)) return 1;
return 0;
}
... потому что вы закончите с неэффективным алгоритмом с точки зрения количество звонков в lessthan
. Если ваш алгоритм не делает ничего полезного, в чем разница между 1 и 0 вернется, то у тебя зря сравнения.
C++ относится к "строгим слабым порядки". Если <
строгий слабый приказывать, и !(a < b) && !(b < a)
, не обязательно следует, что a == b
. Они просто "на одном месте" в заказе, и !(a < b) && !(b < a)
является отношением эквивалентности. Таким образом, компаратор требуется sort
заказы эквивалентности классы объектов, не обеспечивает полный порядок.
единственная разница в том, что вы говорите, когда !(a < b)
. Для строгого полного порядка, вы бы вывести b <= a
читать "меньше или равно". Для строгого слабого порядка, вы не можете определить b <= a
означает b < a || b == a
и это было правдой. C++ педантичен в этом, и поскольку он позволяет оператору перегружать его в значительной степени, так как людям, перегружающим операторы, нужен жаргон, чтобы сообщить пользователям их код, что они могут ожидать с точки зрения того, как операторы относятся. Java говорит о компараторе и хэш-коде, совместимом с equals, что все, что вам нужно. C++ должен иметь дело с , ==, =, пост-условие назначения и так далее.
C++ использует довольно чистый математический подход к этому в API, поэтому все определяется в терминах одного двоичного отношения. Java более дружелюбен в некоторых отношениях и предпочитает трехсторонние сравнения, где определение фундаментальная единица (сравнение) немного сложнее, но логика, ведущая от нее, проще. Это также означает, что алгоритм сортировки получает больше информации за сравнение, что иногда полезно. Например, см. оптимизацию quicksort" голландский флаг", которая является преимуществом, когда в данных много дубликатов" в одном месте".
в этом случае компаратор с тремя значениями является коэффициентом усиления скорости. Но C++ использует согласованное определение компаратора для сортировки, а также для set
и map
, lower_bound
и так далее, которые едва выигрывают от трехзначного компаратора (возможно, сохраните одно сравнение, возможно, нет). Я предполагаю, что они решили не усложнять свой приятный, общий интерфейс в интересах конкретного или ограниченного потенциального повышения эффективности.
моя догадка в C++ это было сделано только для уменьшения дублирования кода: как только вы определяете compare op для класса/типа, вы не только можете сравнить эти объекты, просто написав a
Что касается сортировки, нам нужно только меньше, чем оператор, зачем вводить дополнительные вещи? :)
Если вы ссылаетесь на std:: sort(), его использование только меньше оператора (), потому что ему не нужно сохранять относительный порядок эквивалентного элемента, поэтому ему понадобится только меньше оператора() и неявно больше оператора ().
в то время как с std::stable_sort сохранит его, но он медленнее. ему нужно меньше оператора() и двунаправленного итератора в обмен на оператор equal() для построения "trivalue" compare function