2-路归并排序以及Java实现(学习笔记)
1.步骤
(1)把n个有序表两两组合,组合要保证新序列有序,得到ceil(n/2)个序列。(ceil表示向上取整)
(2)2-路归并排序就是重复步骤(1),直到只有1个序列。
(3)举例说明(非常简单):
2.性能分析
(1)时间复杂度
最好最坏平均情况下都是O( nlog(n) )
因为序列两两组合趟数为floor( log(2,n) ),而两两组合需要时间为O(n),得到最终的O( nlog(n) )
(2)空间复杂度
每趟组合需要一个数组辅助,空间界限为O(n)
(3)稳定性
稳定的,两两组合能保证指针指向元素值相等时候,前一个序列优先。故相等元素先后顺序不改变。
3.Java代码实现
(1)Java可以比较任意两个对象大小,我之前的博客有提到(https://blog.csdn.net/weixin_42111859/article/details/104132520),这里用int举例子(扩展到任意对象相当轻松)
(2)我并没有使用递归实现
(3)涉及到了有序表拼接的知识,L1[1,2,…,m]和L2[1,2,…,m]拼接的时间复杂度为O(m+n)
(4)代码中@Test是JUnit单元测试,放在主函数中运行是一样的
代码如下:
private static int[] b;
// 拼接有序表,可优化的
private static void jointOrderedList(int[] array, int st1, int ed1, int st2, int ed2) {
//此方法调用前,要求b已经被初始化
int st = st1;
int bIndex = 0;
while (true) {
if (st1 < ed1 && st2 < ed2) {
if (array[st1] <= array[st2]) {
b[bIndex++] = array[st1];
st1++;
} else {
b[bIndex++] = array[st2];
st2++;
}
continue;
} else if (st1 < ed1 && st2 >= ed2) {
b[bIndex++] = array[st1];
st1++;
continue;
} else if (st1 >= ed1 && st2 < ed2) {
b[bIndex++] = array[st2];
st2++;
continue;
} else {
break;
}
}
for (int i = 0; i < bIndex; i++) {
array[st++] = b[i];
}
}
public static void mergeSort(int[] array) {
b = new int[array.length];
int len = 1;
for (int i = 1; i <= Math.floor(array.length / 2.0); i++) {
for (int st = 0; st < array.length; ) {
int ed = st + len * 2 > array.length ? array.length : st + len * 2;
jointOrderedList(array, st, st + len, st + len, ed);
st = ed;
}
len *= 2;
}
}
@Test
public void testMergeSort() {
int[] a = {
4, 7, 9, 6, 5, 2, 3};
System.out.println(Arrays.toString(a));
mergeSort(a);
System.out.println(Arrays.toString(a));
}
运行结果:
注解:代码中有序表拼接的判断可以用变量表示,防止重复判断,更好一点
转载请注明出处,谢谢合作