トライバルの比較機能と比較して、オペレーターよりも少ないオペレーターを使用してソートする
-
24-09-2019 - |
質問
C ++/STLでは、オペレーターよりも少ないオペレーターのみを使用して並べ替えが行われます。 altough私は、ソートアルゴリズムが実際にどのように実装されているのか分かりません。他の操作がインクライトが作成されていると仮定します。
a > b *equals* b < a == true
a == b *equals* !(a < b) && !(b < a)
たとえばJavaのように、Trivalue*比較関数を使用することと比較すると、これはパフォーマンスに適していますか、なぜこの設計上の決定が下されたのですか?
私の仮定では、3つの比較機能は、これらの比較自体をまだ実装し、同じパフォーマンスをもたらす必要があるということです。
** Trivalue Compare関数とは、-1、0、および1をより少ない、等しく、より高く戻す比較関数を意味します*
アップデート:宇宙船のようです <=>
オペレーターはC ++ 20に来ているので、明らかに委員会は使用するだけの欠点があると考えました operator<
.
解決
ある意味では、他の2つは暗黙的ですが、より正確なのは、比較の種類が実際にはないと言うことです 必要 Tri-Valuedコンパレータと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つのリターンと0のリターンの違いに役立つことを何もしない場合、比較を無駄にしました。
C ++は、「厳格な弱い順序」を指します。もしも <
厳格な弱い秩序です !(a < b) && !(b < a)
, 、そうではありません 必要な それに従ってください a == b
. 。彼らは注文の「同じ場所」であり、 !(a < b) && !(b < a)
同等の関係です。したがって、コンパレータは必要とします sort
注文 同等のクラス オブジェクトのうち、合計順序は提供されません。
それがする唯一の違いは、あなたが言うことです !(a < b)
. 。厳密な合計順序のために、あなたは推測するでしょう b <= a
, 、「より低いか等しい」と読みます。厳格な弱い秩序の場合、定義することはできません b <= a
意味する b < a || b == a
そして、これを真実にしてください。 C ++はこれについてPedanticであり、オペレーターのオーバーロードが必要なため、オペレーターがオペレーターの関係者をユーザーに伝えるために専門用語を必要とするため、オペレーターがオペレーターの関係に関して期待できることを伝えるために、オペレーターがそれを過負荷にする必要があるためです。 Javaはコンパレータとハッシュコードが平等と一致していることについて話します。 C ++は、<、>、==、<=、> =、割り当てのポストコンディショニングなどに対処する必要があります。
C ++は、APIでこれに対して非常に純粋な数学的アプローチを取っているため、すべてが単一のバイナリ関係の観点から定義されます。 Javaはいくつかの点で友好的であり、基本ユニット(比較)の定義がもう少し複雑であるが、それから導くロジックがより簡単である場合、3方向の比較を好む。また、ソートアルゴリズムが比較ごとにより多くの情報を取得することを意味します。たとえば、「ダッチフラグ」クイックソートの最適化を参照してください。これは、データに「同じ場所に」多くの「同じ場所」が重複している場合の利点です。
その場合、3値コンパレータは速度ゲインです。しかし、C ++は、並べ替えと、 set
と map
, lower_bound
など、3つの価値のあるコンパレータの恩恵を受けることはほとんどありません(おそらく1つの比較を保存しないかもしれません)。彼らは、特定のまたは限られた潜在的効率の向上のために、彼らの素晴らしい、一般的なインターフェースを複雑にしないことを決めたと思います。
他のヒント
C ++では、コードの重複を減らすためだけに行われました。クラス/タイプで比較OPを定義すると、A <Bを書くだけでそれらのオブジェクトを比較できるだけでなく、のセットをソートする能力も得ることができます。そのようなオブジェクト。
並べ替えに関しては、オペレーターよりも少ないだけで、なぜ追加のものを導入する必要がありますか? :)
STD :: sort()を参照している場合、その使用は、同等の要素の相対的な順序を保持する必要がないため、より少ない()演算子のみを使用するため、より少ない()演算子、暗黙的に大きい()演算子が必要になります。
std :: stable_sortはそれを保存しますが、遅いです。 equal()演算子と引き換えに、より少ない()演算子と双方向のイテレーターが必要です。