排序算法是否需要传递性


14

是否可以将排序算法与非传递性比较一起使用?如果是,为什么将传递性列为排序比较器的要求?

背景:

  • 排序算法通常根据比较器函数C(x,y)对列表的元素进行排序,其中

    C(x,y)={1if xy0if xy+1if xy

    据我了解,此比较器的要求是:

    • 自反: x:C(x,x)=0
    • 反对称: x,y:C(x,y)=C(y,x)
    • 传递性: x,y,z,a:C(x,y)=aC(y,z)=aC(x,z)=a
    • 为所有x和y定义C(x,y),并且结果仅取决于x和y

    (这些要求在不同的实现中总是以不同的方式列出,因此我不确定我是否正确)

现在我想知道一个“容忍的”比较器函数,如果,则接受数字x,y相似x y | 1Ç X ÿ = { - 1 ,如果 X < ý - 1 0 如果| x y | 1 + 1 如果 X > ÿ + 1|xy|1

C(x,y)={1if x<y10if |xy|1+1if x>y+1

实例:两者[ 1, 2, 3, 4, 5][1, 4, 3, 2, 5]根据比较宽容以升序排序正确(,如果x来在列表中在y之前) ,但不是,因为C(4,2)= 1C(x,y)0
[1, 4, 2, 3, 5]

这种宽容的比较器是自反的和不对称的,但不能传递。

即C(1,2)= 0,c(2,3)= 0,但是C(1,3)= -1,违反了传递性

但是,我无法想到在给定该比较器和随机列表的情况下不会产生“正确排序”输出的任何排序算法。

因此,在这种情况下是否不需要传递性?排序是否需要不太严格的传递性版本?

相关问题:


我认为使用[3,2,1]上的比较器将“总是选择中间”作为枢轴的quicksort会失败。
G. Bach 2013年

2
我怀疑某些排序算法中使用的某些非传递比较器可能会导致无限循环。
KarolisJuodelė2013年

1
aiai+1aiajij

@ G.Bach我认为,如果您的数组有n次3次,n次2次,n次1次,并且中间的2个被用作第一个枢轴,那么无论随后发生什么,quicksort实际上都会完全失败。
gnasher729

Answers:


11

您问:我们可以运行排序算法,向其提供非传递性比较器吗?

答案:当然可以。您可以使用任何输入来运行任何算法。

但是,您知道规则:垃圾进场,垃圾进场。如果使用非传递比较器运行排序算法,则可能会得到无意义的输出。特别是,不能保证根据您的比较器对输出进行“排序”。因此,使用非传递比较器运行排序算法不太可能像您希望的那样有用。

[3,2,1]


1
我首先想到的是列表[3,2,1] 根据我的比较器排序的,因此排序当然应该保持不变;但我可能使用了错误的排序定义。我只是将每个元素与其直接相邻的元素进行比较,但这可能太弱了,无法考虑对列表进行排序
HugoRune

4
@HugoRune嗯,这很有趣。是什么意思排序?如果您可以显示排序算法将在给定的非传递比较器的情况下终止,并且每当算法终止时,某些条件为真,并且该条件就是您要进行排序的条件……那么,当然,该算法将对列表进行排序每次,对于排序的定义。如果比较器不是可传递的,则采用对sorted的定义可能是没有意义的,因为它需要对排序列表中的所有元素进行成对比较。
Patrick87 2013年

3
@HugoRune,如果“仅比较邻居”,则可能需要自定义排序。标准算法假定传递性,以避免多余的比较。或者,您也可以将非传递性订单嵌入传递性订单中。或者,也许您正在寻找一些与拓扑排序类似的东西?
vonbrand 2014年

我碰到了一段时间,发现气泡排序实际上工作得很好,因为它只比较相邻的元素。
Mooing Duck

4

给定一组元素和二进制排序关系,需要传递性才能完全排序元素。实际上,甚至需要传递性来定义元素的部分顺序。 http://en.m.wikipedia.org/wiki/总订单

为了对元素进行排序而不需要传递性,您需要对“ sorted”的含义进行更广泛的定义。很难做到自洽。另一个答案是:“尤其不能保证根据您的比较器对输出进行'排序'。” 但是我们实际上可以说出更强的话。您可以确保不会根据比较器对输出进行排序

a<bb<cc<a


1
我将问题解释为使用部分排序进行排序(这样的比较表明事物不相等是可传递的,而那些认为项目是不可区分的则不是)。基于部分排序的排序有时很有用,但在最坏的情况下,需要进行N(N-1)/ 2个比较。由于我的回答中所述的原因,在最坏的情况下进行少于N(N-1)/ 2个比较的任何排序算法都将无法正确排序部分排序的商品。
supercat

2

听起来好像您想要的是对项目进行排列,以使所有可辨别的排名都是正确的,但是接近的项目可能被认为“无法区分”。可以设计适用于此类比较的排序算法,但是除非对可以报告事物难以区分的比较数量有限制,否则无法避免让它们需要N(N-1)/ 2个比较。要了解原因,请选择一些数字N和任何比N(N-1)/ 2个比较少的排序算法。然后填充列表L [0..N-1],将每个元素L [I]设置为I / N,然后使用比较器对其进行“排序”(最小值为0,最大值为(N-1)/ N ,因此差异为(N-1)/ N,小于1)。

因为可以比较N(N-1)/ 2个项目对,并且排序没有进行太多比较,所以必须有一些不直接相互比较的项目对。将其中一个最终以1进行排序的对象替换为另一个,然后将其替换为-1 / N,将所有项目恢复到其初始位置,然后重复排序操作。就像第一次一样,每个比较操作将产生零,因此将执行相同的比较,并且项目将以相同的顺序结束。为了使列表正确排序,“ 1”必须在“ -1 / N”之后排序(因为它们相差一个以上),但是由于排序算法永远不会将这两个项目直接进行比较,因此无法知道这一点。


0

用值n,n-1,n-2,...,2、1填充n个元素的数组。然后尝试使用“直接插入”算法进行排序。您会发现每个元素都被认为等于它之前的元素,因此不会移动。“排序”的结果是相同的数组。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.