• 八大排序之归并排序


    一、基本思想

       归并排序,将当前序列分成若干个小的有序序列,然后逐个合并成更大的有序序列。这里所谓的若干个小的有序序列即是将序列分割成n个长度为1的序列,然后两两合并成长度为二的有序序列。然后在将这长度为二的有序序列合并为长度为四的有序序列。依次类推,最终达到原序列长度,这样,排序就完成了。这其实是归并排序递归回溯过程的描述。归并排序的正序描述可以是这样,将序列分成两个子序列,对两个子序列进行归并排序,然后将两个子序列合并到原序列中。

    二、实现步骤

       归并排序,有两个需要解决的问题:一、如何划分子区间。二、如何合并子区间。

      划分子区间:

      这里采用两路归并排序,即将当前序列划分成两个子序列。

      合并子区间:

      由于子区间是有序的,所以在合并过程中不会有很大的复杂度,一次遍历即可。

      思想已经陈述完毕,下面看代码,有详细注释。

    三、实现代码

       随机数组测试类 点击这里

    package sort;
    
    import sort.util.*;
    
    public class MergingSort implements ISort{ 
    
        //private static int[] c = null;
        //将有序序列a[left] ~ a[middle]和a[middle+1] ~ a[right]合并到数组b中,返回数组b
        private void merge(int[] a , int left ,  int middle , int right) {
            int[] b = new int[a.length];
            for(int i = 0; i < a.length; i++) {            //将数组a复制到b中
                b[i] = a[i];
            }
            int i = left ,  j = middle + 1 ,  k = left;
            while(i <= middle && j <= right) {             //合并过程,选择较小的,逐个赋值。
                if(b[i] < b[j]) a[k++] = b[i++];
                else a[k++] = b[j++];
            }                                              //循环结束,说明有一个有序序列已经遍历完毕
            while(i <= middle) {a[k++] = b[i++];}          //将剩余的部分直接复制到a数组中
            while(j <= right) {a[k++] = b[j++];}           //这两个循环只有一个能被执行
            
        }
        
        //对a[left] ~ a[right]进行归并排序,排序后的结果放在b[]中
        private void mergeSort(int[] a , int left , int right) {
            if(left != right) {                             //当进行归并排序的数组只有一个元素      
                int middle = (left + right) / 2;            //划分成两部分进行归并
                mergeSort(a , left , middle);               //左边部分进行归并排序
                mergeSort(a , middle+1 , right);            //右边部分进行归并排序
                merge(a , left , middle , right);           //左右排序完成后进行合并
            }
        }
        
        public void sort(int[] array){
            mergeSort(array , 0 , array.length-1);
        }
        public static void main(String[] args) {
            int[] array = RandomArrayGenerator.getRandomArray(100 , 30);
            SortTestHelper.test(new MergingSort() , array);
        }
    }

    测试结果:

    四、总结分析

       时间复杂度:O(n log n)   合并复杂度为n,递归过程的复杂度为log2n

      空间复杂度:O(n)             需要一个辅助数组

      稳定性:稳定。

      八大排序中其余两个nlogn复杂度的堆排序和快速排序是不稳定的,较普通排序更快的希尔排序也是不稳定的。本文所讲的归并排序却是稳定的,而且效率也很可观。

      本文个人编写,水平有限,如有错误,恳请指出,欢迎讨论分享

  • 相关阅读:
    【PAT甲级】1128 N Queens Puzzle (20分)
    Codeforces Global Round 7D(马拉车/PAM,回文串)
    【PAT甲级】1127 ZigZagging on a Tree (30分)(已知中序后序蛇形输出层次遍历)
    SDOI2012 体育课
    APIO2018 Circle selection 选圆圈
    [科技] 求数列的前k次方和
    APIO2016 Fireworks
    CTSC2018 暴力写挂
    ZJOI2018 胖
    SDOI2017 数字表格
  • 原文地址:https://www.cnblogs.com/wanghang-learning/p/9209321.html
Copyright © 2020-2023  润新知