1. 基本思想

什么是归并排序??

归并排序是基于归并的排序。归并,是将两个或两个以上的有序表合成一个有序表。

假设待排序的数组有 n 个元素,将数组看成是 n 个有序的子数组,每个子数组只有一个元素。然后两两合并,得到每个子数组长度为2。然后继续两两合并,直到合并为长度为 n 的数组。

时间复杂度

平均复杂度是 O(nlogn),最好复杂度是 O(nlogn),最坏复杂度是 O(nlogn)

(图片来源于网络)

将原数组划分子数组的过程看成是一棵二叉树,那么数组划分到每个子数组中只有一个元素时的二叉树高度(递归深度)。最后一层是叶子节点,每个叶子节点是一个元素。那么,最后一层的节点个数是 n (数组长度)。假设二叉树深度是 k ,那么,从 2^(k-1) = n 得到,klogn 。合并的过程是从子数组(其中只有一个元素)开始向上合并

每次排序需要遍历一次数组,时间是 O(n) 。一共需要 logn 趟排序(二叉树的深度,递归深度)。所以时间复杂度是 O(nlogn)

空间复杂度

空间复杂度是 O(n)

每次排序中都需要一个数组暂时保存排序前的数组或者是排序后的结果数组,数组占用的空间是 n (数组的长度)。

使用场景

归并排序是稳定的排序。也就是,相等的元素的顺序不会改变。归并排序的速度仅次于快速排序。一般用于总体是无序的,但是子序列是相对有序的。

2. 代码实现(java)

public void sort(int[] array)  {mergeSort(array, 0, array.length);
}public void mergeSort(int[] array, int low, int high) {if (low >= high) return;int mid = (low + high) / 2;  // 将数组一分为二mergeSort(array, 0, mid);  // 对左边一半进行排序mergeSort(array, mid, high);  // 对右边一半进行排序merge(array, low, mid, high);  // 将两个有序子数组合并为一个有序数组
}// 将数组左右两半合并为一个排好序的数组。左右两个子数组已经是排好序的数组
public void merge(int[] array, int low, int mid, int high) {// 将数组array复制到一个新数组copy中,将排序完成后的值写入原数组arrayint[] copy = Arrays.copyOf(array, array.length);  // 复制int i = low, j = mid, k = low;// 逐一比较两个子数组,小者排在前面。直至其中一个数组全部写入结果数组中while (i < mid && j < high) {if (copy[i] <= copy[j]) array[k++] = copy[i++];  // 相等的元素,相对位置不改变else array[k++] = copy[j++];}// 如果左边的子数组中剩余的数据写入数组中while (i < low) array[k++] = copy[i++];// 如果右边的子数组中剩余的数据写入数组中while (j < high) array[k++] = copy[j++];
}/**********************************************************************/
// 将两个有序子数组合并为一个有序数组。第一个有序子数组是[low,mid),第二个有序子数组是[mid,high)
public void merge(int[] array, int low, int mid, int high) {// 将数组array复制到一个新数组copy中,将排序完成后的值写入原数组arrayint[] res = new int[array.length];  // 复制int i = low, j = mid, k = low;// 逐一比较两个子数组,小者排在前面。直至其中一个数组全部写入结果数组中while (i < mid && j < high) {if (array[i] <= array[j]) res[k++] = array[i++];else res[k++] = array[j++];}// 如果左边的子数组中剩余的数据写入数组中while (i < low) res[k++] = array[i++];// 如果右边的子数组中剩余的数据写入数组中while (j < high) res[k++] = array[j++];// 把结果数组res中[low,high)中的部分复制到原数组中,从而改变原数组for (i = low, k = low; i < high; i++, k++) {array[k] = res[i];}
}

3. 代码说明

public void mergeSort(int[] array, int low, int high) {if (low >= high) return;int mid = (low + high) / 2;  // 将数组一分为二mergeSort(array, 0, mid);  // 对左边一半进行排序mergeSort(array, mid, high);  // 对右边一半进行排序merge(array, low, mid, high);  // 将排好序的两部分合并为一个排好序的数组
}

mergeSort() 是一个递归函数。递归的过程就像是一个下楼梯的过程。在递归时,调用一次自己,就下一个台阶(调用),直到下到最后一个(终止条件),然后想上返回到第一个台阶(回溯)。

归并排序,向下划分,向上合并的过程。在向下调用自身的过程,把数组一分为二,一次次的划分,直到数组中的一个元素单独成为一个子数组。mergeSort(array, low, mid)mergeSort(array, mid, high) 是调用自身划分的过程。合并是发生在划分之后,merge(array, low, mid, high) 是把两个升序的子数组合并为一个升序的数组,也是递归中回溯做的事情。

归并排序 MergeSort相关推荐

  1. 基本排序算法之4——归并排序mergesort

    归并排序理论上时间复杂度只有O(NlogN),但是其中存在过多临时内存分配和copy操作而不适用于内存排序,却是外部排序的基本思路.下面是我的实现: #include<iostream> ...

  2. 数据结构--链表--单链表归并排序mergesort

    思路: 1.将链表的中点找到,对其切分成2条 2.继续步骤1,切成4条,8条...,直至每段链表只有1个元素 3.归并操作,对两两链表进行合并排序,并返回回并后的链表的头结点,依次向上递归回去 C++ ...

  3. 【排序】归并类排序—归并排序(逆序数问题)

    文章目录 前言 归并排序(merge sort) 逆序数 结语 微信公众号:bigsai 数据结构与算法专栏 前言 在排序中,我们可能大部分更熟悉冒泡排序.快排之类.对归并排序可能比较陌生.然而事实上 ...

  4. PHP实现归治算法,PHP排序算法系列之归并排序详解

    归并排序 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序 ...

  5. c++归并排序_合并排序法

    一.合并排序(Merge Sort) 就是将多个有序数据表合并成一个有序数据表.如果参与合并的只有两个 有序表,那么称为二路合并.对于一个原始的待排序序列,往往可以通过分割的方法来归结为多路合 并排序 ...

  6. 数据结构排序法之堆排序he归并排序

    堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法.堆是一个近似完全二叉树的结构,并同时满足堆性质:即子结点的键值或索引总是小于(或者大于)它的父节点. 堆排序的时间,主要由建立初始 ...

  7. 快速排序伪代码_归并排序之入门到quot;放弃quot;

    归并排序之入门到"放弃" 前面我们已经讲解过了冒泡排序.选择排序.插入排序. 希尔排序.本次我们将讲解归并排序,希望大家学习完之后,能够徒手快速手写一个归并排序的实现代码. 由来 ...

  8. 快速排序算法_经常用到的的排序(快速排序和归并排序)简单的计算机算法学习...

    1.快速排序 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排序由C. A. R. Hoare在1960年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的 ...

  9. 排序算法-归并排序详细图解

    归并排序: 采用了分治策略 就是将原问题分解为一些规模较小的相似子问题,然后递归解决这些子问题,最后合并其结果作为原问题的解. 归并的核心思想 将两个有序的数组合并成一个大的有序的数组,通过递归把待排 ...

  10. 数据结构(八):排序 | 插入排序 | 希尔排序 | 冒泡排序 | 快速排序 | 简单选择排序 | 堆排序 | 归并排序 | 基数排序 | 外部排序 | 败者树 | 置换-选择排序 | 最佳归并树

    文章目录 第八章 排序 一.排序的基本概念 (一)什么是排序 (二)排序的应用 (三)排序算法的评价指标 (四)排序算法的分类 (五)总结 二.插入排序 (一)算法思想 (二)算法实现 (三)算法效率 ...

最新文章

  1. 《Python知识手册》,V3.0版来了,2021年,走起!
  2. 用java做一个简单记事本_用记事本写一个简单的java程序
  3. JAVA shell grep
  4. 关于利用VS2008创建项目遇到的小困惑备忘
  5. 【机卓14蒋海平-U201411018】机电传动控制课程-《自动化技术中的进给电气传动》第一章的1.1节和1.2节——读书笔记整理...
  6. .5-浅析express源码之Router模块(1)-默认中间件
  7. DB2之CLOB对象用法
  8. linux怎么点亮硬盘灯_一种基于Linux系统下测试Expander背板硬盘指示灯的方法及系统与流程...
  9. 小甲鱼python笔记_小甲鱼Python笔记(类)
  10. 《上海市居住证》签注和积分确认流程指南
  11. echart可视化图表多条折线显示数据混乱问题
  12. 讲解NRF24L01P无线收发模块(转载)
  13. 简述GPS,GSM,GPRS和GNSS的名称区别
  14. 上海大学计算机跨考限制,注意:跨考专业有限制!这些你必须要了解!
  15. 计算机应用基础网络统考操作,(全套)知识点练习-计算机应用基础-(网络统考-操作题-共152题)...
  16. 燕教授助力公益,已种下60000棵树,修复荒漠78万平方米
  17. bsf dfs 专题(一)
  18. 计算机网络摘要怎么写,计算机网络实践论文摘要怎么写 计算机网络实践论文摘要范文参考...
  19. [统计学知识点]卡方检验
  20. PowerShell 学习笔记 - 1 PS Core 基础

热门文章

  1. Ubuntu常用软件安装
  2. 软件测试工程师简历模板(三年经验)
  3. matlab2016b版本安装
  4. 互联网创新创业大赛优秀范例_【互联网+大学生创新创业大赛项目计划书】创新创业大赛作品范例...
  5. 兄弟打印机内存已满清零方法_兄弟打印机清零大全
  6. 三菱plc与计算机无协议通讯,三菱PLC编程口协议与专用协议的区别
  7. 软件设计文档国家标准—软件需求说明书(GB856T——88)
  8. java8.0安装教程_jdk8安装教程详解
  9. JDK的安装 - JDK8(1.8.0_301)
  10. TheFatRat自动化渗透工具