经典排序算法之:归并排序

1,背景及原理

归并排序(英语:Mergesort),是建立在归并操作上的一种有效的排序算法,效率为O(nlogn)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法的一个非常典型的应用,且各层分治递归可以同时进行。

2,算法思路

  • 基本思路

归并排序就是先递地分解数组,再合数组。下面是实现过程:

首先考虑下如何将二个已经排好序的数列合并。这个很简单,只要从比较二个数列的第一个数,谁小就先取谁,取的数存放在一个辅助数组里面,取后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

那么如何才能让这两个数组内数据分别有序呢?可以将A,B组各自再分成二组。依次类推,不断进行递归,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。

  • 可视轨迹

这里写图片描述

  • 实例程序
public class Merge {

    public static void sort(Comparable[] a) {
        //辅助数组
        Comparable[] aux = new Comparable[a.length];
        sort(a, aux, 0, a.length-1);

    }

    // 递归实现子数组有序
    private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) {
        if (hi <= lo) return;
        int mid = lo + (hi - lo) / 2;
        sort(a, aux, lo, mid);
        sort(a, aux, mid + 1, hi);
        merge(a, aux, lo, mid, hi);
    }
    // 合并两个有序数组
    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
        // 先将a数组复制到aux辅助数组中
        for (int k = lo; k <= hi; k++) {
            aux[k] = a[k]; 
        }
        // 再合并到a数组中
        int i = lo, j = mid+1;
        for (int k = lo; k <= hi; k++) {
            if      (i > mid)              a[k] = aux[j++];
            else if (j > hi)               a[k] = aux[i++];
            else if (less(aux[j], aux[i])) a[k] = aux[j++];
            else                           a[k] = aux[i++];
        }
    }

    // v是否小于w ?
    private static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w) < 0;
    }      

    // 交换a[i]和a[j]
    private static void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }

    // 打印数组到输出
    private static void show(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+" ");  
        }
        System.out.println();
    }

    // 测试函数
    public static void main(String[] args) {
        Comparable[] a = new Comparable[]
                {'B','F','S','R','T','J','D','A','Z','V','Y','H','K','I','P','Q','C','G','N','U','M','E','O'};
        System.out.print("排序前:");
        show(a);
        System.out.print("排序后:");
        Selection.sort(a);
        show(a);
    }
}

【程序输出】

排序前:B F S R T J D A Z V Y H K I P Q C G N U M E O 
排序后:A B C D E F G H I J K M N O P Q R S T U V Y Z 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值