美文网首页
归并排序(dart实现)

归并排序(dart实现)

作者: 锦鲤跃龙 | 来源:发表于2020-11-07 12:14 被阅读0次

归并排序

1945年由约翰:冯.诺伊曼(John von Neumann)首次提出

执行流程

  1. 不断的将当前序列品骏分割成两个子序列,直到不能再分割(序列中只剩下1个元素)
  2. 不断的将两个子序列合并成1个有序序列,直到最终只剩下一个有序序列

思路

  • 将一个数组归并排序,就是将左边的数组归并,右边的数组归并,然后进行合并,递归下去

  • 合并的思路:

    • 创建两个索引分别指向两个数组,
    • 将两个归并的数组都从头开始,
    • 比如发现左边数字比较小,拿出左边数字放入大数组,左边索引右移一位,
    • 发现右边的数字比较小,拿出右边的数字放入大数组,右边索引右移一位
    • 最终两个索引都到最后即可

    难点:
    需要合并的两个数组在同一个数组中,并且是挨在一起,
    解决方法,将左边的数组备份出来

dart代码


class MergeSort<T extends Comparable<T>> extends Sort<T> {
  List<T> leftCopy ;
  @override
  sort() {
    leftCopy = List(list.length>>1);//提前定义一般长度的左边长度
    _sort(0, list.length);
  }

  ///
  /// Author: liyanjun
  /// description:  对 [begin, end) 范围的数据进行归并排序
  ///
  _sort(int begin, int end) {
    if (end - begin < 2) return;
    int mid = (end + begin) >> 1; //找到中间位置
    _sort(begin, mid); //左边归并排序
    _sort(mid, end); //右边归并排序
    _merge(begin, mid, end); //合并
  }

  ///
  /// Author: liyanjun
  /// description: 归并
  ///将 [begin, mid) 和 [mid, end) 范围的序列合并成一个有序序列
  _merge(int begin, int mid, int end) {
    int leftCopyIndex = 0; //左边的数组
    int leftCopyLength = mid - begin; //左边数组长度
    int rightIndex = mid; //右边数组索引 基于原数组
    int resultIndex = begin; //覆盖的索引
    for (var i = 0; i < leftCopyLength; i++) {
      leftCopy[i]  = list[begin + i];
    } //复制左边的数组
    while (leftCopyIndex < leftCopyLength) {
      //复制的数组遍历完即可,因为两个都是有序数组
      //如果左边数组元素小于右边数组元素,将右边数组元素放在目标索引 ,反之左边数组放入目标索引
      if (rightIndex < end && cmpElement(list[rightIndex], leftCopy[leftCopyIndex]) < 0) {//考虑稳定性,所以不用等于好
        list[resultIndex] = list[rightIndex];
        rightIndex += 1; //右边数组右移动一位
      } else {
        list[resultIndex] = leftCopy[leftCopyIndex];
        leftCopyIndex += 1; //左边数组右移动一位
      }
      resultIndex += 1; //目标数组索引移动一位
    }
  }


}

执行结果

排序前 :[20, 12, 6, 20, 17, 14, 13, 4, 19, 10]
排序后 :[4, 6, 10, 12, 13, 14, 17, 19, 20, 20]
【MergeSort<num>】
耗时:0.002s (2ms)     比较:22    交换:0
-----------------

复杂度分析

归并排序花费的时间

T(n) = 2*T(n/2) + O(n)
推导过程:
\because
T(1) = O(1);
T(n)/n = T(n/2)/(n/2) + O(1);

S(n) = T(n)/n
则有
S(1)=O(1)
S(n)= S(n/2)+O(1) = S(n/4)+O(2) = S(n/8)+O(3)=S(n/2^k)+O(k)=S(1)+O(logn)= O(logn)

\therefore
T(n) = n * S(n) = n*O(logn) = O(nlogn)

由于归并排序总是平均分割子序列,所以最好、最坏、平均时间复杂度都是O(nlogn),属于稳定排序
从代码中不难看出:归并排序的空间复杂度是 O(n/2 + logn) = O(n)
n/2用于临时存放左侧数组,logn是因为递归调用

常见的递推公式和时间复杂度

递推式 时间复杂度
T(n) = T(n/2) + O(1) O(logn)
T(n) = T(n-1) + O(1) O(n)
T(n) = T(n/2) + O(n) O(n)
T(n) = 2*T(n/2) + O(1) O(n)
T(n) = 2*T(n/2) + O(n) O(nlogn)
T(n) = T(n-1) + O(n) O(n^2)
T(n) = 2*T(n-1) + O(1) O(2^n )
T(n) = 2*T(n-1) + O(n) O(2^n)

相关文章

  • 归并排序(dart实现)

    归并排序 1945年由约翰:冯.诺伊曼(John von Neumann)首次提出 执行流程 不断的将当前序列品骏...

  • 算法—排序篇2

    1、归并排序(Merging Sort) 归并排序(Merging Sort): 就是利用归并的思想实现排序⽅法....

  • 归并排序&快速排序

    归并排序 利用归并的思想实现排序方法,该算法采用经典的分治策略,分而治之。 代码实现 基础设置 归并排序 —— 非...

  • 算法

    分类 排序 希尔排序 代码实现 归并排序 代码实现 查找

  • java归并排序

    归并排序什么是归并排序:图解归并排序归并排序有两种实现方式,一是基于递归,而是基于迭代1)基于递归的归并排序: 基...

  • 排序算法之归并排序

    归并排序(Merge Sort) 归并排序是利用归并的思想实现排序的方式,该算法采用的是经典的分治算法 归并排序过...

  • JavaScript实现排序算法

    实现了冒泡,选择,插入,快排,希尔,归并 冒泡排序 选择排序 插入排序 快速排序 希尔排序 归并排序

  • 算法排序之归并排序和快速排序

    归并排序和快速排序用的都是分治的思想,用递归的编程技巧来实现.咱们先来看归并排序. 归并排序 归并排序的核心思想就...

  • 数据结构与算法学习-归并排序和快速排序

    代码准备: 归并排序 归并排序(Merging Sort) 就是利用归并的思想实现排序方法. 它的原理是假设初始序...

  • 归并排序

    图解排序算法(四)之归并排序 基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用...

网友评论

      本文标题:归并排序(dart实现)

      本文链接:https://www.haomeiwen.com/subject/vyzxbktx.html