证明合并排序是稳定的
Proving mergesort is stable
我写了一个合并排序算法。当我运行以下测试时:
public static void main(String[] args){
Integer[] arr = {3,7,9,11,0,-5,2,5,8,8,1};
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.asList(arr)); // asList() returns fixed size list, so can't pass to mergesort()
List<Integer> result = mergesort(list);
System.out.println(result);
}
我得到 [-5, 0, 1, 2, 3, 5, 7, 8, 8, 9, 11]
,这是正确的。但是,我知道mergesort是一种稳定排序,那么如何编写一个测试来证明这两个8的顺序是原来的顺序呢?
编辑:由于我使用了 Integer
class,而不是原始整数,我想我可以得到 hashCode()
因为 Integer
扩展了基础 Object
class.
然而,当我尝试
Integer[] arr = {3,7,9,11,0,-5,2,5,8,8,1};
System.out.println(arr[8].hashCode());
System.out.println(arr[9].hashCode());
我只得到:
8
8
我能想到的最好方法是将数字包装在它们的包装器中 Integer
class。如果您执行以下操作:
Integer eight = new Integer(8);
Integer anotherEight = new Integer(8);
a == b; //Returns false
a.equals(b); //Returns true
否则,如评论中所建议,您可以在 class 中添加一个额外字段以进行比较。
编辑:为了回答您的编辑,Integer.hashcode()
文档指出 hascode 是
equal to the primitive int value represented by this Integer object.
我认为使用简单的键值结构,比如 this or some of that
使用这个(简称):
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
你可以这样做:
public static void main(String[] args)
{
Integer[] arr = {new Tuple(3,0),new Tuple(7,1),new Tuple(9,2) ,new Tuple(11,3), new Tuple(0,4), new Tuple(-5,5), new Tuple(2,6), new Tuple(5,7), new Tuple(8,8), new Tuple(8,9), new Tuple(1,10)};
List<Tuple<Integer,Integer>> list = new ArrayList<>();
list.addAll(Arrays.asList(arr)); // asList() returns fixed size list, so can't pass to mergesort()
List<Integer> result = mergesort(list);
System.out.println(result);
}
而在合并排序的代码中,只合并第一项,让第二项相同,你应该先看到(8,8),然后看到(8,9)
稳定性证明将涉及分析合并排序算法,而不是创建稳定性测试未失败的测试用例。首先分析自下而上的归并排序可能更简单。首先 n 个元素的数组被视为长度为 1 的 n 运行s 的数组,然后重复合并这些 运行s 直到产生单个排序的 运行。在 k 路合并排序中,如果来自 k 运行 的当前元素相等,则将最左边的元素 运行 移动到输出数组,保持稳定性。
对于通常为 2 向的自上而下归并排序,适用相同的规则,当遇到相等元素时,移动左侧 运行 的元素,保持稳定性。
我写了一个合并排序算法。当我运行以下测试时:
public static void main(String[] args){
Integer[] arr = {3,7,9,11,0,-5,2,5,8,8,1};
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.asList(arr)); // asList() returns fixed size list, so can't pass to mergesort()
List<Integer> result = mergesort(list);
System.out.println(result);
}
我得到 [-5, 0, 1, 2, 3, 5, 7, 8, 8, 9, 11]
,这是正确的。但是,我知道mergesort是一种稳定排序,那么如何编写一个测试来证明这两个8的顺序是原来的顺序呢?
编辑:由于我使用了 Integer
class,而不是原始整数,我想我可以得到 hashCode()
因为 Integer
扩展了基础 Object
class.
然而,当我尝试
Integer[] arr = {3,7,9,11,0,-5,2,5,8,8,1};
System.out.println(arr[8].hashCode());
System.out.println(arr[9].hashCode());
我只得到:
8
8
我能想到的最好方法是将数字包装在它们的包装器中 Integer
class。如果您执行以下操作:
Integer eight = new Integer(8);
Integer anotherEight = new Integer(8);
a == b; //Returns false
a.equals(b); //Returns true
否则,如评论中所建议,您可以在 class 中添加一个额外字段以进行比较。
编辑:为了回答您的编辑,Integer.hashcode()
文档指出 hascode 是
equal to the primitive int value represented by this Integer object.
我认为使用简单的键值结构,比如 this or some of that
使用这个(简称):
public class Tuple<X, Y> {
public final X x;
public final Y y;
public Tuple(X x, Y y) {
this.x = x;
this.y = y;
}
}
你可以这样做:
public static void main(String[] args)
{
Integer[] arr = {new Tuple(3,0),new Tuple(7,1),new Tuple(9,2) ,new Tuple(11,3), new Tuple(0,4), new Tuple(-5,5), new Tuple(2,6), new Tuple(5,7), new Tuple(8,8), new Tuple(8,9), new Tuple(1,10)};
List<Tuple<Integer,Integer>> list = new ArrayList<>();
list.addAll(Arrays.asList(arr)); // asList() returns fixed size list, so can't pass to mergesort()
List<Integer> result = mergesort(list);
System.out.println(result);
}
而在合并排序的代码中,只合并第一项,让第二项相同,你应该先看到(8,8),然后看到(8,9)
稳定性证明将涉及分析合并排序算法,而不是创建稳定性测试未失败的测试用例。首先分析自下而上的归并排序可能更简单。首先 n 个元素的数组被视为长度为 1 的 n 运行s 的数组,然后重复合并这些 运行s 直到产生单个排序的 运行。在 k 路合并排序中,如果来自 k 运行 的当前元素相等,则将最左边的元素 运行 移动到输出数组,保持稳定性。
对于通常为 2 向的自上而下归并排序,适用相同的规则,当遇到相等元素时,移动左侧 运行 的元素,保持稳定性。