歸併排序(非遞歸實現)

在這裏插入圖片描述
注意

  • 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]);
		}
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章