自顶向下的归并排序

自顶向下归并排序

图解

原理

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(divide and conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

算法分析

  • 稳定性

归并排序是一种稳定的排序。

  • 存储结构要求

可用顺序存储结构。也易于在链表上实现。

  • 时间复杂度

对长度为n的文件,需进行 趟二路归并,每趟归并的时间为o(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是o(nlgn)。

  • 空间复杂度

需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为o(n),显然它不是就地排序。

代码实现

public static void order4(int[] a) {
  sort(a,0,a.length-1);
}

public static void sort(int[] data,int left,int right) {
  if(left >= right) return;
  //找出中间索引
  int center = (left + right)/2;
  //对左边数组进行递归
  sort(data, left, center);

  //对右边数组进行递归

  sort(data, center+1, right);

  //合并

  merge(data,left,center,right);

}

public static void merge(int[] data,int left, int center,int right) {
  //临时数组

  int[] tmpArr = new int[data.length];

  //右数组第一个元素索引

  int mid = center + 1;

  //third 记录临时数组的索引

  int third = left;

  //缓存左数组第一个元素的索引

  int tmp = left;

  while (left <= center && mid <=right) {
  //从两个数组中取出最小的放入临时数组

  if (data[left] <= data[mid]) {
    tmpArr[third++] = data[left++];

  } else {
    tmpArr[third++] = data[mid++];
  }
}

  //剩余部分依次放入临时数组(实际上两个while只会执行其中一个)

  while(mid <= right) {
    tmpArr[third++] = data[mid++];
  }

  while(left <= center) {
    tmpArr[third++] = data[left++];
  }

  //将临时数组中的内容拷贝回原数组中
  while (tmp <= right) {
    data[tmp] = tmpArr[tmp++];
  }
}
posted @ 2021-03-17 22:20  唐坣  阅读(243)  评论(0编辑  收藏  举报