我不了解尝试解决稳定排序算法的潜在问题。
Arrays.sort(Object[])
Javadoc声明:
这种保证是稳定的:相同的元素会 不能因排序而重新排序。
但如果元素相等,它们就不会彼此分裂!如果你交换两个相等的元素,这不应该影响任何东西。这是平等的定义。
那么,为什么我们需要稳定呢?
更新:我的问题是关于Collections.sort(List<T>)
/ Objects.sort(Object[])
方法,而不是Collections.sort(List<T>, Comparator<T>)
,Objects.sort(Comparator<T>)
。后者有点不同。但是它们仍然不需要稳定性:如果你想要可预测的化合物排序,那么你就可以创建合适的化合物比较器。
答案 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
- 价格
您可以看到几个用例,您希望按Product
或id
排序price
,而不是按其他值排序。
稳定排序带来的最大好处是,如果您按price
排序,然后按 id
排序,那么您将List
正确排序先按price
排序,然后按id
排序。
如果排序算法不稳定,那么第id
排序可能会按price
打破初始排序的顺序。