分治法----普通歸併排序和自然歸併排序(java實現)

1、普通歸併排序

歸併排序算法的基本思想是將待排序元素分成大小大致相同的兩個子序列,分別對這兩個字序列進行排序,最終將排好序的子序列合併爲所要求的序列。歸併排序算法完全依照下面3個步驟進行。

(1)分解。將n個元素分成各含n/2個元素的子序列。

(2)求解。用歸併排序對兩個子序列遞歸地排序。

(3)合併。合併兩個已經排好序的子序列以得到排序結果。

核心代碼如:

void MergeSort(int a[],int p,int r){
        int q;
        if(p<r){
            q=(p+r)/2;
            MergeSort(a, p, q);
            MergeSort(a,q+1,r);
            Merge(a,p,q,r);
        }
    }

 

 

完工代碼如下:

​import java.util.Arrays;
import java.util.Scanner;
public class MergeSort1 {
    public static void main(String args[]) {
        MergeSort1 mer = new MergeSort1();
        Scanner input = new Scanner(System.in );
        System.out.print("請輸入要排序的個數:");
        int n = input.nextInt();
        int [] array = new int [n];
        System.out.print("請輸入排序數:");
        for(int i=0;i<n ;i++)
            array[i] = input.nextInt();
        System.out.println("原數據:" + Arrays.toString(array));
        mer.MergeSort(array,0,n-1);
        System.out.println("排序以後:" + Arrays.toString(array));
    }
    void Merge(int a[],int p,int q ,int r){
        int n1=q-p+1;
        int n2=r-q;
        int i,j ,k;
        int L [] = new int [n1+1];
        int R [] = new int [n2+1];
        for(i=0;i<n1;i++){
            L[i]=a[p+i];
        }
        for(j=0;j<n2;j++){
            R[j]=a[q+j+1];
        }
       L[n1]=R[n2]=1000;
        i= 0;
        j= 0;
        for(k=p;k<r+1;k++){
            if(L[i]<R[j]){
                a[k]=L[i];
                i++;
            }
            else{
                a[k]=R[j];
                j++;
            }
        }
    }
    void MergeSort(int a[],int p,int r){
        int q;
        if(p<r){
            q=(p+r)/2;
            MergeSort(a, p, q);
            MergeSort(a,q+1,r);
            Merge(a,p,q,r);
            System.out.println("分治遞歸排序以後:" + Arrays.toString(a));
        }
    }
}
​

結果截圖


2、自然歸併排序

算法描述:對於初始給定的數組,通常存在多個長度大於1的已自然排好序的子數組段.例如,若數組a中元素爲{4,8,3,7,1,5,6,2},則自然排好序的子數組段有{4,8},{3,7},{1,5,6},{2}.用一次對數組a的線性掃描就足以找出所有這些排好序的子數組段.然後將相鄰的排好序的子數組段兩兩合併,構成更大的排好序的子數組段({3,4,7,8},{1,2,5,6}).繼續合併相鄰排好序的子數組段,直至整個數組已排好序。

核心代碼如下:

public void mergeSort(int[] a) {
        int len = 0;
        while(indexLen(0,a)<a.length){
            for (int i = 0,k1=0,k2=0; i < a.length; ) {
                k1=indexLen(i,a);
                k2=indexLen(k1,a);
                merge(a, i, k1,k2);
                i=i+k1+k2;
            }
        }
    }

完工代碼如下:

import java.util.Arrays;
import java.util.Scanner;
public class Sort {
    public static void main(String args[]) {
        Sort mer = new Sort();
        Scanner input = new Scanner(System.in );
        System.out.print("請輸入要排序的個數:");
        int n = input.nextInt();
        int [] array = new int [n];
        System.out.print("請輸入排序數:");
        for(int i=0;i<n ;i++)
            array[i] = input.nextInt();
        System.out.println("原數據:" + Arrays.toString(array));
        mer.mergeSort(array);
        System.out.println("排序以後:" + Arrays.toString(array));
    }
//判斷數組有序子序段的長度
    int indexLen(int j,int [] a) {

        int k=j+1;
        int len=1;
        for (; ;) {
            if(k>=a.length)
                break;
            if(a[j]<a[k]) {
                len++;
                j++;
                k++;
            }
            else break;
        }
        return len;
    }
    int index=0;
    public void Printf(int a[]){
        index=indexLen(index,a);
    }
    public void mergeSort(int[] a) {
        int len = 0;
        while(indexLen(0,a)<a.length){
            for (int i = 0,k1=0,k2=0; i < a.length; ) {
                k1=indexLen(i,a);
                k2=indexLen(k1,a);
                merge(a, i, k1,k2);
                i=i+k1+k2;
                System.out.println("相鄰兩組合並排序以後:" + Arrays.toString(a));
            }
        }
    }
    public void merge(int[] a, int i, int len1,int len2) {
        int start = i;
        int X = i + len1;// 歸併的前半部分數組
        int j = i + len1;
        int Y = j + len2;// 歸併的後半部分數組
        int[] temp = new int[len1+len2];
        int count = 0;
        while (i < X && j < Y && j < a.length) {
            if (a[i] <= a[j]) {
                temp[count++] = a[i++];
            }
            else {
                temp[count++] = a[j++];
            }
        }
        while (i < X && i < a.length) {
            temp[count++] = a[i++];
        }
        while (j < Y && j < a.length) {
            temp[count++] = a[j++];
        }
        count = 0;
        while (start < j && start < a.length) {
            a[start++] = temp[count++];
        }
    }
}

結果截圖

 

發佈了15 篇原創文章 · 獲贊 10 · 訪問量 2234
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章