归并排序(非递归实现)

在这里插入图片描述
注意

  • 1.在递归实现中,向下划分的过程中并没有实际操作。实际交换位置等merge操作是从底端向上进行的
  • 2.因此递归过程可消除,避免不必要的系统开销

代码实现:


import java.util.Scanner;

public class 归并非递归实现 {
    
    
	/**
     * 归并排序(非递归)
     * (合并内部已排好序的两两相邻数组)从切分的数组长度为1开始,一次归并变回原来长度的2倍
     * @param nums 待排序数组
     * @return 排好序的数组
     */
	static int[] mergSort(int a[]) {
    
    
		int len=1;
		while(len<=a.length) {
    
    //while终止条件
			for(int i=0;i+len<a.length;i+=len*2) {
    
    
			//for循环终止条件为当剩下的元素数量不超过一组时(即没有第二组与之合并了)
				int lb=i,ub=i+len*2-1,mid=i+len-1;
				if(ub>a.length-1) {
    
    
					ub=a.length-1;//整个待排序数组为奇数的情况
				}
				merge(a,lb,mid,ub);
				//其中[low,mid],[mid+1,high]为两组已排好序的数组,
				//各自的长度为len;后者长度可能不满len,这只可能出现在原数组元素个数为奇时。
			}
			len*=2;
		}
		return a;
	}
	    /**
     * 将合并起来的两个内部已排序数组归并排序,同递归版,
     * 先将左半部分存在L,右半部分存在R,然后直接对原数组进行修改。
     * @param nums 带排序数组
     * @param low 左边数组第一个元素索引
     * @param mid 左边数组最后一个元素索引,mid + 1为右边数组第一个元素索引
     * @param high 右边数组最后一个元素索引
     */
	static void merge(int a[],int lb,int mid,int ub) {
    
    
		int n1=mid-lb+1;
		int n2=ub-mid;
		int L[]=new int[n1+1];
		int R[]=new int[n2+1];
		for(int i=0;i<n1;i++) {
    
    
			L[i]=a[lb+i];
		}
		for(int i=0;i<n2;i++) {
    
    
			R[i]=a[mid+1+i];
		}
		L[n1]=R[n2]=Integer.MAX_VALUE;
		int i=0,j=0;
		for(int k=lb;k<=ub;k++) {
    
    
			if(L[i]<=R[j]) {
    
    
				a[k]=L[i];
				i++;
			}else {
    
    
				a[k]=R[j];
				j++;
			}
		}
	}
	public static void main(String args[]) {
    
    
		Scanner sc=new Scanner(System.in);
		int k=sc.nextInt();
		int a[]=new int[k];
		for(int i=0;i<k;i++) {
    
    
			a[i]=sc.nextInt();
		}
		a = mergSort(a);
		for(int i=0;i<k;i++) {
    
    
			System.out.println(a[i]);
		}
	}

猜你喜欢

转载自blog.csdn.net/qq_42021845/article/details/106885482