• 四、归并排序(mergesort)


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

    排序类别

    排序方法

    时间复杂度

     

     

    空间复杂度

    稳定性

    复杂性

     

     

    平均情况

    最坏情况

    最好情况

     

     

     

    归并排序

    归并排序

    O(nlog2n)

    O(nlog2n)

    O(nlog2n)

    O(n)

    稳定

    较复杂

    归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

    分而治之

     可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n

    合并相邻有序子序列

    再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

     代码实现:

     
     1 public class MergeSort{
     2     private static <AnyType extends Comparable <? super AnyType>> void mergeSort(AnyType[] a,AnyType[] tmpArray,int left,int right){
     3         if(left < right){
     4             int center = (left + right)  /2;
     5             mergeSort(a, tmpArray, left, center);
     6             mergeSort(a, tmpArray, center + 1, right);            //
     7             merge(a, tmpArray, left, center + 1, right);          //
     8         }
     9     }
    10     
    11     public static <Anytype extends Comparable<? super Anytype>> void mergeSort(Anytype[] a){
    12         Anytype[] tmpArray = (Anytype[]) new Comparable[a.length];
    13         mergeSort(a, tmpArray, 0, a.length-1);
    14     }
    15     
    16     private static<AnyType extends Comparable<? super AnyType>>void merge(AnyType[] a,AnyType[] tmpArray,int leftPos,int rightPos,int rightEnd){
    17         int leftEnd = rightPos - 1;
    18         int tmpPos = leftPos;
    19         int numElements = rightEnd - leftPos + 1;
    20         while(leftPos <= leftEnd && rightPos <= rightEnd){
    21             if(a[leftPos].compareTo(a[rightPos]) <= 0)
    22                 tmpArray[tmpPos++] = a[leftPos++];
    23             else
    24                 tmpArray[tmpPos++] = a[rightPos++];
    25             }
    26         while(leftPos <= leftEnd){
    27                 tmpArray[tmpPos++] = a[leftPos++];
    28             }
    29         while(rightPos <= rightEnd){
    30                 tmpArray[tmpPos++] = a[rightPos++];
    31         }
    32         for(int i = 0; i < numElements; i++, rightEnd--){
    33             a[rightEnd] = tmpArray[rightEnd];
    34         }
    35     }
    36     
    37     private static <AnyType> void printPart(AnyType[] a,int begin,int end){
    38         for(int i = 0; i < begin; i++){
    39             System.out.print("	");
    40         }
    41         for(int i = begin; i <= end; i++){
    42             System.out.print(a[i] + "	");
    43         }
    44         System.out.println();
    45     }
    46     
    47     @Test
    48     publicvoidtestMergeSort(){
    49         MergeSort ms = new MergeSort();
    50         Integer[] a = new Integer[]{81,94,11,96,12,35,17,95,28,58,41,75,15};
    51         System.out.print("排列前:	");
    52         ms.printPart(a, 0, a.length-1);
    53         ms.mergeSort(a);
    54         System.out.print("排列后:	");
    55         ms.printPart(a, 0, a.length-1);
    56     
    57 }

     

    代码:1. 递归实现“分”,需要原数组啊a[a.length],临时数组tmp[a.length]            mergeSort(a, tmpArray, left, right);

        2.分后治:merge(a, tmpArray, left, center + 1, right);

    a.比较左右大小,逐渐赋值给tmpArray

    b.左右分别取完,逐渐赋值给tmpArray

    c.再将tmpArray[i]赋值给a[i]

  • 相关阅读:
    Linux 使用 github 常用命令
    配置使用 git 秘钥连接 GitHub
    Python 使用 face_recognition 人脸识别
    face_recognition 基础接口
    pycharm 安装激活操作
    Python 人工智能之人脸识别 face_recognition 模块安装
    Linux pip 命令无法使用问题
    vue 起步
    vue.JS 介绍
    AngularJS 简介
  • 原文地址:https://www.cnblogs.com/PureJava/p/10617743.html
Copyright © 2020-2023  润新知