非递归的归并排序(详细解析)

如果说递归是自上到下解决问题,那么非递归就是自下而上解决问题

归并的非递归思想是:

将原数组首先进行两个元素为一组进行排序,然后合并为四个一组进行排序,八个一组进行排序,直至合并整个数组;

如下图:

在这里插入图片描述

我们合并的序列分为左子序列与右子序列,假设每个序列的长度为s=2, i 的初始值为0,则如下图
在这里插入图片描述


 //一次归并过程
 private static void mergepass(int[] a, int[] b, int s) {
  // TODO Auto-generated method stub
  int i = 0;
  // 如果数组的长度为偶数,将相邻的两个数值恰好能两两比较
  while (i <= a.length - 2 * s) {// 右子序列的右边界i+2s-1<=a.length-1即i<=a.length-2s
   mergeSort(a, b, i, i + s - 1, i + 2 * s - 1);
   i = i + 2 * s;
  }
  //不为偶数时
  if (i < a.length - s) {// 左子序列的右边界i+k-1<n,这个判断条件就保证了肯定存在右子序列,且剩余元素仍可分为两个子数组段,只不过第二个数组段不满。
   mergeSort(a, b, i, i + s - 1, a.length - 1);
  } else {// 剩余数组不满一个数组,直接合并到b里
   for (int j = i; j < a.length; j++) {
    b[i] = a[i];
   }
  }
 }

全部代码为:

 public static void main(String[] args) {
  int a[] = new int[] { 49, 38, 65, 97, 76, 13, 27 };
  merge(a);
  System.out.println("排列好的数组:");
  for (int c : a) {
   System.out.print(c + " ");
  }
 }

private static void merge(int[] a) {
  // TODO Auto-generated method stub
  int[] b = new int[a.length];
  int s = 1;
  while (s < a.length) {
   mergepass(a, b, s);// 先将排列好的数组赋值给中间数组b
   mergepass(b, a, s);// 再将b的值赋给a
   s += s;// 每次翻倍,1/2/4/8...
  }
 }
 
 private static void mergepass(int[] a, int[] b, int s) {
  // TODO Auto-generated method stub
  int i = 0;
  // 如果数组的长度为偶数,将相邻的两个数值恰好能两两比较
  while (i <= a.length - 2 * s) {// 右子序列的右边界i+2s-1<=a.length-1即i<=a.length-2s
   mergeSort(a, b, i, i + s - 1, i + 2 * s - 1);
   i = i + 2 * s;
  }
  //不为偶数时
  if (i < a.length - s) {// 左子序列的右边界i+k-1<n,这个判断条件就保证了肯定存在右子序列,且剩余元素仍可分为两个子数组段,只不过第二个数组段不满。
   mergeSort(a, b, i, i + s - 1, a.length - 1);
  } else {// 剩余数组不满一个数组,直接合并到b里
   for (int j = i; j < a.length; j++) {
    b[i] = a[i];
   }
  }
 }
 //归并排序
 private static void mergeSort(int[] a, int[] b, int left, int mid, int right) {
  int p1 = left, p2 = mid + 1, k = left;// p1,p2是检测指针,k是存放指针
  while(p1<=mid&&p2<=right){
  if (a[p1] < a[p2]) {
    b[k++] = a[p1++];
   } else {
    b[k++] = a[p2++];
   }
  }
 while(p1<=mid){// 如果第一个序列未检测完,直接将后面所有元素加到合并的序列中
 b[k++] = a[p1++];
 }
 while (p2 <= right) {// 如果第二个序列未检测完,直接将后面所有元素加到合并的序列中
   b[k++] = a[p2++];
  }
  for (int i = left; i <= right; i++) {
   a[i] = b[i];
  }


发布了4 篇原创文章 · 获赞 6 · 访问量 64

猜你喜欢

转载自blog.csdn.net/weixin_42524410/article/details/105015591
今日推荐