分治法----普通归并排序和自然归并排序(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++];
        }
    }
}

结果截图

发布了14 篇原创文章 · 获赞 9 · 访问量 287

猜你喜欢

转载自blog.csdn.net/weixin_44392808/article/details/104147588