排序算法---合并排序(Merge Sort)

合并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。
合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。合并排序也叫归并排序。


算法基本思想:

  1. 首先将未排序的数组,进行拆分成n个单一的数据。
  2. 然后将这n个数据按照索引顺序,两两组合、排序。(例如:有8个数据,那么第一个和第二个组合,第三个和第四个组合。。。如有未组合的数据这放任其暂时不管)
  3. 将上面已经两两组合、排序好的数据看成是一个“元素”,再进行两两组合、排序。。。
  4. 重复上述的步骤,最后就得到已经排序好的数组。
示意图

代码实现:

import java.util.Arrays;
import java.util.Date;

/**
 * Created by noonbiteun
 * Date: 2017/8/1
 */
public class MergeSort {
    private static void merge(int[] unsortArr, int frontIndex, int backIndex, int lastIndex, int[] sortArr) {
        int i = frontIndex;//前半段的起始索引
        int j = backIndex;//后半段的起始索引
        int k = 0;
        //合并两个小分组
        while (i < backIndex && j < lastIndex) {
            if (unsortArr[i] < unsortArr[j]) {
                sortArr[k++] = unsortArr[i++];
            } else {
                sortArr[k++] = unsortArr[j++];
            }
        }
        while (i < backIndex) {
            //前半段还有数据
            sortArr[k++] = unsortArr[i++];
        }
        while (j < lastIndex) {
            //后半段还有数据
            sortArr[k++] = unsortArr[j++];
        }
        for (int l = 0; l < k; l++) {
            //将排序好的数放回
            unsortArr[frontIndex + l] = sortArr[l];
        }
    }


    public static void sort(int[] arr, int first, int last, int[] sorted) {
        if (first < last - 1) {
            int back = (first + last) / 2;
            sort(arr, first, back, sorted);
            sort(arr, back, last, sorted);
            merge(arr, first, back, last, sorted);
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[10];
        //初始化数组
        for (int i = 0; i < 10; i++) {
            arr[i] = (int) (Math.random() * (100 + 1));
        }
        long t1 = new Date().getTime();
        System.out.println("原始的顺序: "+ Arrays.toString(arr));
        MergeSort.sort(arr, 0, arr.length, new int[arr.length]);
        long t2 = new Date().getTime();
        System.out.println("排序后顺序: "+ Arrays.toString(arr));
        System.out.println("耗时:"+(t2-t1)+" ms");
    }
}

输出结果:

运行结果

分析小结:

归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的...
    Luc_阅读 6,807评论 0 35
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 10,605评论 0 52
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 9,098评论 0 15
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 5,034评论 0 2
  • 1 我说:“为什么会轮到我头上?” 我说:“为什么不会轮到我头上呢?” 2 每每遇到一件另我苦恼的事情,我总会这样...
    三人生阅读 2,540评论 0 0

友情链接更多精彩内容