归并排序详解,与其他排序算法的比较

归并排序

将两个有序的数组归并成一个更大的有序数组

一种简单的方法是:将两个数组归并到第三个数组中(需要额外的空间)

更常见的做法是:避免了开辟额外空间,采用原地归并的方式

原地归并的抽象方法

public static void merge(Comparable[] a, int lo, int mid, int hi){
// 将大数组a分成两个小数组,a[lo, mid], a[mid, hi] 分别进行排序
int j = mid+1;
int i = lo;
// 数组复制,复制到辅助数组中
System.arraycopy(a, lo, aux, lo, hi);
for(int k = lo; k <= hi; k++) {
if (i > mid) // 当左侧小数组为空时
a[k] = aux[j++];
else if (j > hi) // 当右侧小数组为空时
a[k] = aux[i++];
// 比较左右两个数组首位,如果aux[j]小于aux[i]
else if (less(aux[j], aux[i]))
// 将 aux[j] 放入原数组 并索引下移
a[k] = aux[j++];
else // 否则将 aux[i] 放入原数组 并索引下移
a[k] = aux[i++];
}
}

自顶向下的归并排序

算法讲究先从上直接递归到最小数组,将最小数组排序

步骤:

  1. 通过递归将数组不断二分,直到小数组只含有两个元素为止
  2. 将只含有两个元素的数组排序后,再重新组成上层数组
  3. 如此反复,直到大数组为止

在这里插入图片描述

package Sort;
import java.util.Arrays;
import java.util.Random;
import static Sort.SortExample.isSorted;
import static Sort.SortExample.less;
public class MergeSort {
public static Comparable[] aux;
// 主函数,供外界调用
public static void sort(Comparable[] b){
Comparable[] a = new Comparable[b.length];
System.arraycopy(b, 0, a, 0, b.length);
// System.out.println(Arrays.toString(b));
aux = new Comparable[a.length]; // 1000
sort(a, 0, a.length-1); // 1000
}
// 通过递归将大数组不断划分,直到每个小数组只有两个元素
public static void sort(Comparable[] a, int lo, int hi){
// 将数组a[lo..hi] 排序
if(hi <= lo)
return;
int mid = lo + (hi-lo)/2; // 4
sort(a, lo, mid); // 左半边排序
sort(a, mid+1, hi); // 右半边排序
merge(a, lo, mid, hi); // 归并结果
}
}

自底向上的归并排序

从最小数组开始排序,再排序较大数组,循环渐进地进行

public class MergeSortBU {
public static void sort(Comparable[] b){
Comparable[] a = new Comparable[b.length];
System.arraycopy(b, 0, a, 0, b.length);
// 进行 lgN 次两两归并
int N = a.length;
Comparable[] aux = new Comparable[N];
for(int sz = 1; sz < N; sz *= 2){ // 以2个元素为一个最小数组
for(int lo = 0; lo < N-sz; lo += sz+sz) // 以相邻的两个小数组为一组进行归并
merge(a, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1)); // 将相邻的两个小数组归并
if(!isSorted(a))
System.out.println("自底向上归并排序失败");
}
}
}

特点:

  • 可以用来实现对链表的排序,只需要重新组织链表连接就能将链表原地排序

注意点:

  • 归并排序的空间复杂度不是最优的
  • 在实践中不一定会遇到最坏情况
  • 除了比较,算法的其他操作(例如:访问数组)也很重要
  • 不进行比较也能将某些数据排序

四种排序算法的比较

数据来源:algo4 官方提供的 algo4-data.zip 数据包

先进行1k数据量的比较:

选择排序,1000个数据,执行时间为:0.01177 s
插入排序,1000个数据,执行时间为:0.0137114 s
希尔排序,1000个数据,执行时间为:0.0014275 s
自顶向下归并排序,1000个数据,执行时间为:0.001443 s
自底向上归并排序,1000个数据,执行时间为:3.711E-4 s

进行32k数据量的比较:

选择排序,32000个数据,执行时间为:4.2373938 s
插入排序,32000个数据,执行时间为:2.6435673 s
希尔排序,32000个数据,执行时间为:0.0226827 s
自顶向下归并排序,32000个数据,执行时间为:0.0186592 s
自底向上归并排序,32000个数据,执行时间为:0.0120077 s

其他有关排序算法的文章:
选择排序,插入排序,希尔排序的详解与比较

快速排序算法详解与其他排序算法的比较

本文作者:清澈的澈

本文链接:https://www.cnblogs.com/lmc7/p/17531393.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   清澈的澈  阅读(9)  评论(0编辑  收藏  举报  
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示