与Trivalue比较函数相比,仅使用较低的操作员进行排序
-
24-09-2019 - |
题
在C ++/STL中,仅使用较低的操作员完成。 Altough我不知道如何实际实施分类算法,我认为创建了其他操作是隐含的:
a > b *equals* b < a == true
a == b *equals* !(a < b) && !(b < a)
与使用Trivalue*比较函数(例如Java)相比,这对性能是否有益,或者为什么做出设计决定?
我的假设是,任何三字比较函数仍然必须本身实现这些比较,从而导致相同的性能。
**通过Trivalue比较函数,我的意思是一个比较函数,该函数的返回-1、0和1的返回-1、0和1,小于相等,高于**
更新:似乎是一艘太空船 <=>
运营商进入C ++ 20,因此显然委员会认为只有使用 operator<
.
解决方案
从某种意义上说,其他两个是隐式的,但更准确的是说比较实际上不是 需要 三值比较器和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确实谈论了比较器,并且标题与平等一致,这就是您所需要的。 C ++必须处理<,>,==,<=,> =,分配后的条件等等。
C ++在API中采用了相当纯粹的数学方法,因此所有内容都是根据单个二进制关系定义的。 Java在某些方面更友好,并且更喜欢三向比较,在这种情况下,基本单元(比较)的定义更为复杂,但是从中引导的逻辑更为简单。这也意味着该类型算法每次比较获得更多信息,偶尔有用。例如,请参见“荷兰标志” QuickSort优化,当数据中有很多“在同一位置”重复项时,这是一个好处。
在这种情况下,三值比较器是速度增益。但是C ++使用比较器的一致定义进行排序以及 set
和 map
, lower_bound
依此类推,这几乎无法从三值比较器中受益(也许可以节省一个比较,也许不是)。我猜他们决定不为特定或有限的潜在效率提高而复杂化他们的良好,一般界面。
其他提示
我在C ++中的猜测只是为了减少代码重复:一旦定义了类/类型上的比较OP,您不仅可以通过简单地编写a <b进行比较,而且还可以获得分类的设置这样的对象。
至于排序,我们只需要比操作员不太介绍,为什么还要介绍其他内容? :)
如果您指的是std :: sart(),则仅使用少()操作符,因为它不需要保留等效元素的相对顺序,因此它将仅需要较少()operator,而隐含地又是更大()operator。
而std :: stable_sort将保留它,但速度较慢。它需要少()操作员和双向迭代器,以交换均等()操作员来构建“ Trivalue”比较函数