尽管没有保留原始顺序,为什么python的排序称为稳定?

时间:2017-09-01 10:41:17

标签: python algorithm sorting

摘要

从Python 2.2开始,Python中的排序保证稳定,如文档herehere所述。

Wikipedia解释了稳定属性对算法行为的意义:

  

如果有两个记录R和S具有相同的密钥,并且R出现在原始列表中的S之前,则排序算法是稳定的,那么R将始终出现在排序列表中的S之前。

但是,在排序对象(如元组)时,排序会出现不稳定。

例如,

>>> a = [(1, 3), (3, 2), (2, 4), (1, 2)]
>>> sorted(a)
[(1, 2), (1, 3), (2, 4), (3, 2)]

然而,为了被认为是稳定的,我认为新序列应该

[(1, 3), (1, 2), (2, 4), (3, 2)]

因为,在原始序列中,元组(1, 3)出现在元组(1, 2)之前。 sorted功能依赖于2-ary"键"当1-ary"键"是平等的。 (澄清一下,某个元组{1}}的1-ary键将为t和2-ary t[0]。)

为了产生预期结果,我们必须执行以下操作:

t[1]

我猜测我的错误假设是关于>>> sorted(a, key=lambda t: t[0]) [(1, 3), (1, 2), (2, 4), (3, 2)] 还是关于在比较期间如何处理元组和/或列表类型。

问题

  1. 为什么sorted函数被称为"稳定"即使它以这种方式改变原始序列?
  2. 不会将默认行为设置为sorted版本的行为更符合"稳定"手段?为什么不这样设置?
  3. 这种行为是否仅仅是元组和/或列表固有比较的副作用(即错误的假设)?
  4. 感谢。

    请注意,这是关于默认行为是否有用,常见或其他内容。它是关于默认行为一致是否具有稳定的定义(其中,恕我直言,似乎并非如此)和文档中提到的稳定性保证。

3 个答案:

答案 0 :(得分:4)

考虑一下 - (1, 2)出现在(1, 3)之前,不是吗?默认情况下对列表进行排序并不会自动意味着"只需根据第一个元素"对其进行排序。否则,您可以说apple在字母表中aardvark之前。换句话说,这与稳定性无关。

The docs也很好地解释了listtuple等数据结构是按字典顺序排序的:

  

特别是,通过比较相应的元素,按字典顺序比较元组和列表。这意味着要比较相等,每个元素必须比较相等,并且两个序列必须是相同的类型并具有相同的长度。

答案 1 :(得分:2)

稳定排序从排序的角度保持那些被认为相等的元素的顺序。因为元组按字典顺序逐个元素进行比较,(1, 2)(1, 3)之前,所以它应该先行:

>>> (1, 2) < (1, 3)
True

答案 2 :(得分:1)

元组的密钥是由所有项目组成的。

>>> (1,2) < (1,3)
True