归并排序

归并排序
过程:
1. 分解 分解待排序的n个元素的序列 成各具n/2个元素的两个子序列
2. 解决 使用归并排序递归地排序两个子序列
3. 合并 合并两个已排序的子序列以产生已排序的答案
注:当待排序的序列长度为1时,递归“开始回升”,在这种情况下无需做任何工作,因为长度为1的每个序列已经排好序
算法

//一次归并过程
//A为数组,p,q,r分别为数组下标 且满足 p<=q<r
//假设子数组A[p…q]和A[q+1…r]都已经排序好 合并后为A[p…r]
MERGE(A,p,q,r) 
    n1=q-q+1
    n2=r-q
let L[1…n1+1]和 R[1…n2]为新的数组
for i=1 to n1
        L[i]=A[p+i-1]
for j=1 to n2
        R[j]=A[q+j]
L[n1+1]为无穷大
R[n2+1]为无穷大
i=1
j=1
for k=p to r
        if L[i] <= R[j]
        A[k]=L[i]
        i=i+1
    else 
        A[k] = R[j]
        j=j+1



//归并排序
MERGE-SORT(A,p,r)
    if(p < r)
        q=(p+r)/2
        MERGE-SORT(p,q)
            MERGE-SORT(q+1,r)
        MERGE(p,q,r)

算法复杂度
最好、最坏和平均:nlgn

Java实现

import java.util.Random;

public class  Main{

    private static int N = 10;
    static Random rand = new Random();

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        test_Merge_ASC();
        test_Merge_DES();
    }

    // 测试排序
    private static void test_Merge_ASC() {
        int[] A = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = rand.nextInt(1000);
        }
        System.out.println("排序前:");
        print(A);
        Merge_Sort_ASC(A, 0, A.length - 1);
        System.out.println("排序后(升序):");
        print(A);
    }

    // 测试排序
    private static void test_Merge_DES() {
        int[] A = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = rand.nextInt(1000);
        }
        System.out.println("排序前:");
        print(A);
        Merge_Sort_DES(A, 0, A.length - 1);
        System.out.println("排序后(降序):");
        print(A);
    }

    // 归并排序  升序
    private static void Merge_Sort_ASC(int[] A, int p, int r) {
        if (p < r) {
            int q = (p + r) / 2;
            Merge_Sort_ASC(A, p, q);
            Merge_Sort_ASC(A, q + 1, r);
            Merge_ASC(A, p, q, r);
        }
    }

    // 归并过程 升序
    private static void Merge_ASC(int[] A, int p, int q, int r) {
        int n1 = q - p + 1;
        int n2 = r - q;
        // 为左右创建两个新数组
        int[] L = new int[n1 + 1];
        int[] R = new int[n2 + 1];
        // 为新数组赋值
        for (int i = 0; i < n1; i++) {
            L[i] = A[p + i];
        }
        for (int i = 0; i < n2; i++) {
            R[i] = A[q + 1 + i];
        }
        L[n1] = Integer.MAX_VALUE;
        R[n2] = Integer.MAX_VALUE;
        // 对比 归并
        int i = 0;
        int j = 0;
        for (int k = p; k <= r; k++) {
            if (L[i] <= R[j]) {
                A[k] = L[i];
                i = i + 1;
            } else {
                A[k] = R[j];
                j = j + 1;
            }
        }
    }

    // 归并排序  降序
    private static void Merge_Sort_DES(int[] A, int p, int r) {
        if (p < r) {
            int q = (p + r) / 2;
            Merge_Sort_DES(A, p, q);
            Merge_Sort_DES(A, q + 1, r);
            Merge_DES(A, p, q, r);
        }
    }

    // 归并过程 降序
    private static void Merge_DES(int[] A, int p, int q, int r) {
        int n1 = q - p + 1;
        int n2 = r - q;
        // 为左右创建两个新数组
        int[] L = new int[n1 + 1];
        int[] R = new int[n2 + 1];
        // 为新数组赋值
        for (int i = 0; i < n1; i++) {
            L[i] = A[p + i];
        }
        for (int i = 0; i < n2; i++) {
            R[i] = A[q + 1 + i];
        }
        L[n1] = Integer.MIN_VALUE;
        R[n2] = Integer.MIN_VALUE;
        // 对比 归并
        int i = 0;
        int j = 0;
        for (int k = p; k <= r; k++) {
            if (L[i] > R[j]) {
                A[k] = L[i];
                i = i + 1;
            } else {
                A[k] = R[j];
                j = j + 1;
            }
        }
    }

    // 打印数组
    private static void print(int[] A) {
        // TODO Auto-generated method stub
        for (int i = 0; i < A.length; i++) {
            System.out.print(A[i] + "\t");
        }
        System.out.println();
    }
}

结果截图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值