Сортировка только с использованием менее чем оператора по сравнению с функцией сравнения симпатии

StackOverflow https://stackoverflow.com/questions/2385690

Вопрос

В C ++ / STL сортировка осуществляется с использованием только менее чем оператора. Altough I понятия не имею, как фактически реализованы алгоритмы сортировки, я предполагаю, что другие операции созданы неплимы:

a > b *equals* b < a == true
a == b *equals* !(a < b) && !(b < a)

По сравнению с использованием тренировки * Сравнить функцию, как, например, Java, это хорошо для производительности, или почему это было принято это проектное решение?

Мое предположение состоит в том, что любая функция сравнения тренировок все еще должна реализовать эти сравнения самим собой, что приведет к тому же характеристике.

** по функции сравнения тренировки, я имею в виду функцию сравнения, которая возвращает -1, 0 и 1 за меньшее, равное и выше, чем *

Обновлять:Кажется, космический корабль <=> Оператор вступает в C ++ 20, так что, очевидно, Комитет думал, что были недостатки только operator<.

Это было полезно?

Решение

В некотором смысле, что другие два неявно, но более точные будут бы сказать, что сравнение сортируется на самом деле нужно Три-ценный компаратор и сортировки C ++ реализуются таким образом, чтобы не использовать ни одного, чтобы минимизировать поведение, требуемое для компаратора.

Это было бы неправильно для STD :: Сортировать, чтобы определить и исключительно использовать что-то вроде этого:

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 возвратом и возвратом A 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 говорит о компараторе и Hashcode, который соответствует равным, что это все, что вам нужно. C ++ должен иметь дело с <,>, ==, <=,> =, постуслом присваивания и т. Д.

C ++ принимает довольно чистый математический подход к этому в API, поэтому все определено в терминах одного двоичного отношения. Java является дружелюбным в некоторых отношениях, и предпочитает трехсторонние сравнения, где определение фундаментальной единицы (сравнение) немного более сложнее, но логика, ведущая от нее, проще. Это также означает, что алгоритм сортировки получает больше информации на сравнение, что иногда полезно. Например, см. Оптимизация «Голландский флаг».

В этом случае трех значений компаратор - это усиление скорости. Но C ++ использует последовательное определение компаратора для рода, а также для set а также map, lower_bound И так далее, который едва выиграет от трехточного компаратора (может быть, сохранить одно сравнение, может быть, нет). Я догадаю, что они решили не усложнять их приятный, общий интерфейс в интересах конкретной или ограниченной потенциальной выгоды эффективности.

Другие советы

Мое предположение в C ++ было сделано только для уменьшения дублирования кода: как только вы определите сравнить OP в классе / Type, вы не только можете сравнивать эти объекты, просто написав <b, но и получите возможность сортировки наборов такие объекты.

Что касается сортировки, нам нужно всего меньше, чем оператор, зачем представить дополнительные вещи? :)

Если вы имеете в виду STD :: Сортировать (), его использование только менее () оператора, потому что ему не нужно сохранять относительную упорядочение эквивалентного элемента, поэтому ему потребуется всего меньше () оператора, и неявно больше () оператора.

В то время как STD :: Custant_sort сохранит его, но он медленнее. Это нужно меньше () оператора и двунаправленного итератора в обмен на равный () оператор для создания функции «Трилевация» сравнить функцию

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top