稳定的排序 - 我们真的需要吗?

时间:2015-09-22 07:37:21

标签: java sorting

我不了解尝试解决稳定排序算法的潜在问题。

Arrays.sort(Object[]) Javadoc声明:

  

这种保证是稳定的:相同的元素会       不能因排序而重新排序。

但如果元素相等,它们就不会彼此分裂!如果你交换两个相等的元素,这不应该影响任何东西。这是平等的定义。

那么,为什么我们需要稳定呢?

更新:我的问题是关于Collections.sort(List<T>) / Objects.sort(Object[])方法,而不是Collections.sort(List<T>, Comparator<T>)Objects.sort(Comparator<T>)。后者有点不同。但是它们仍然不需要稳定性:如果你想要可预测的化合物排序,那么你就可以创建合适的化合物比较器。

4 个答案:

答案 0 :(得分:12)

我们假设您有两列。列名和列日期。然后,您首先按日期开始排序列表,然后按名称对它们进行排序。如果您的排序是稳定的,它将产生的是您正确订购名称,如果名称相同,您可以按日期对它们进行排序,因为您的订单是稳定的。但如果您的订单不稳定,您将无法在相同的密钥之间进行任何相对排序。

public static void main (String[] args) 
{
    // your code goes here
    List<FirstNameLastName> list = new ArrayList<FirstNameLastName> ();
    list.add(new("A","B"));
    list.add(new("D","B"));
    list.add(new("F","B"));
    list.add(new("C","C"));
    list.add(new("E","C"));
    list.add(new("B","C"));

    Arrays.sort(list,new Comparator(firstName)); //FIXME
    // A-B , B-C , C-C , D-B , E-C  , F-B
    Arrays.sort(list,new Comparator(lastName)); //FIXME
    // A-B , D-B F-B,B-C,C-C,E-C
    //So as you see here inside the last name B and C each first name 
    //is sorted also

    //However if you just sorted instead directly on last name only
    //A-B , D-B -F,B-C-C,E-C,B-C
}

private class FirstNameLastName {
      String firstName;
      Stirng lastName;
      public FirstNameLastName(String firstName,String lastName) {
          this.firstName = firstName;
          this.lastName = lastName;
       }
 }

答案 1 :(得分:3)

考虑示例

[{1, 'c'}, {2, 'a'}, {3, 'a'}] 

按数字字段排序,但不按字符排序。按字符稳定排序后:

[{2, 'a'}, {3, 'a'}, {1, 'c'}] 

在不稳定的排序后,可以执行以下顺序:

[{3, 'a'}, {2, 'a'}, {1, 'c'}] 

您可以注意到{3, 'a'}{2, 'a'}已重新排序。

Java 8示例(Java API只对对象进行稳定排序):

List<Point> list = Arrays.asList(new Point(1,1), new Point(1,0), new Point(2,1));
list.sort((a,b) -> Integer.compare(a.x,b.x));
System.out.println(list);
list.sort((a,b) -> Integer.compare(a.y,b.y));
System.out.println(list);

答案 2 :(得分:2)

不稳定的排序可能会吸引用户界面。想象一下,您正在使用Windows中的文件浏览器,其中包含歌曲的详细信息视图。您能想象如果您一直单击filetype列以按文件类型排序,并且每次单击它时它会随机重新排序每个类型组中的所有内容吗?

UI中的稳定排序允许我(用户)创建我自己的复合排序。我可以将多种排序链接在一起,例如“按名称排序”,然后“按艺术家排序”,然后“按类型排序”。最终得到的排序优先考虑类型,然后是艺术家,最后是名称。这是因为稳定的排序实际上保留了前一种排序,允许我从一系列基本排序中“构建”我自己的排序!而不稳定的排序则会破坏先前排序类型的结果。

当然,在代码中,您只需制作一个完整定义的大型排序,然后对进行排序和排序,而不是链式“复合”排序像我上面描述的那样。这就是为什么大多数应用程序内部排序都不需要稳定排序的原因。但是当用户点击点击时,稳定的排序是最好/最简单的。

编辑: “我的问题是关于Collections.sort(List<T>) / Objects.sort(Object[])方法”

这些是适用于定义Comparable的任何内容的通用排序。即使对象在技术上并不“相等”,您的类的Comparable实现也可能返回0,因为您可能正在尝试进行特定排序。换句话说,这些方法对Collections.sort(List<T>, Comparator<T>)的自定义排序都是开放的。你可能想要稳定的排序,或者你可能不想。

答案 3 :(得分:1)

您可能(并且几乎总是这样)拥有以下内容的元素:

a.compareTo(b) == 0 and
a.equals(b) == false

List<Product>为例,其中产品具有许多属性:  - ID   - 价格

您可以看到几个用例,您希望按Productid排序price,而不是按其他值排序。

稳定排序带来的最大好处是,如果您按price 排序,然后按 id排序,那么您将List正确排序先按price排序,然后按id排序。

如果排序算法不稳定,那么第id排序可能会按price打破初始排序的顺序。