归并排序

归并算法的是分治思想的一种体现。

归并算法的主要过程分为两步,首先是对需要排序的元素进行分组,首先一分为二(组),然后二分为四(组),在之后四分为八(组),将元素不断的划分,知道每组元素只包括两个,(当然如果需要排序的元素为奇数个,那么必定是有一组元素只包含的一个的)。我们划分之后,在每组元素之内排序,每个小组的元素有序之后,第二部就开始合并,合并的过程中保证两个合并之后分组是有序的。直到最后八合为四,四合为二,二合为一。

归并排序的算法是稳定的。时间复杂度为 n*log2n

归并排序示意图

(注:图片来自于百度百科)

下面是实现的代码:

package com.neway.sort;

/**
 * Created by Neway on 2015/11/15.
 */
public class MergeSort implements Sort {


    public static void main(String args[]) {
        Sort sort = new MergeSort();
        int arr[] = {89, 78, 8, 5, 13, 12, 11, 1, 0};
        sort.sort(arr);
    }

    @Override
    public void sort(int[] arr) {
        divide(arr, 0, arr.length - 1);
    }

    /**
     * 分割数组
     * @param arr 需要排序的数组
     * @param start 被分割的那个分组的起点
     * @param end 被分割的那个分组的末端
     */
    public void divide(int[] arr, int start, int end) {

        /**
         * 如果当前的分组了内只有一元素或者有两个元素,那么我们排序好了之后返回
         */
        if (start == end || end - start == 1) {
            if (arr[start] > arr[end]) {
                int temp = arr[start];
                arr[start] = arr[end];
                arr[end] = temp;
            }
            return;
        }

        /**
         * 如果分组的长度大于1,那就继续分组,
         * 根据待排数组的长度,mid 的值略有不同
         *
         */
        int mid = -1;
        if ((end + start) % 2 != 0) {
            mid = (int) Math.floor((end + start) >> 1);
        } else {
            mid = (end + start) >> 1;
        }

        // 递归调用分组
        divide(arr, start, mid);
        divide(arr, mid + 1, end);

        //分完组之后开始合并
        merge(arr, start, mid, end);
        for (int i : arr) {
            System.out.print(i + " ");
        }
        System.out.println();

    }

    /**
     * 合并两个分组(合并的写法有点繁琐,应该是可以继续优化的)
     * @param arr 需要排序的数组
     * @param start 第一个分组的起点
     * @param mid 第一个分组的末端,第二个分组的起点是 mid + 1
     * @param end 第二个分组的末端
     */
    public void merge(int[] arr, int start, int mid, int end) {
        int startCopy = start;
        int midCopy = mid;
        int[] arrCopy = new int[end - start + 1];
        int index = 0;
        while (start <= midCopy && (mid + 1) <= end) {
            if (arr[start] < arr[mid + 1]) {
                arrCopy[index++] = arr[start];
                start++;
            } else {
                arrCopy[index++] = arr[mid + 1];
                mid++;
            }
        }

        while (start <= midCopy) {
            arrCopy[index++] = arr[start++];
        }

        while ((mid + 1) <= end) {
            arrCopy[index++] = arr[mid + 1];
            mid++;
        }

        for (int i = 0; i < arrCopy.length; i++) {
            arr[startCopy++] = arrCopy[i];
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值