Java与算法之(11) - 合并排序
天下事,合久必分,分久必合。合并排序的基本思想正是先分再合。
例如对3, 1这个数列排序,首先是分,分为3和1两个数列,然后再合并并排序。合并需要额外的辅助空间,即建立一个两个数列长度之和的空数组用于存储合并结果。
合并分为三步:
1)两个数列在起始位置各分配一个"指针",对比指针位置的数字,取较小的数字存入辅助数组。数字被移出的一侧,指针右移一格,再次比较两个指针位置的数字,直到某一侧的指针移出数组以外结束。
2)把左侧数组剩余的数字按顺序移动到辅助数组中
3)把右侧数组剩余的数字按顺序移动到辅助数组中
过程如下图:
下面把两个数组的长度都增加到2,再看一下合并过程:
观察一下这个流程可以看出,这种合并排序的前提是左右两个数列本身是有序的。所以如果对4, 2, 3, 1排序,拆成4, 2和3, 1两个数列显然是不行的,需要继续拆分4, 2为4和2,然后合并为2, 4;拆分右侧为3, 1,然后合并成1, 3。最后合并2, 4和1, 3。
以4, 3, 6, 2, 7, 1, 5为例,完整的排序过程如下图:
来看代码:
- import java.util.Arrays;
 - /**
 - * 合并排序法
 - * Created by autfish on 2016/9/20.
 - */
 - public class MergeSort {
 - public static void main(String[] args) {
 - int[] numbers = new int[] {4, 3, 6, 2, 7, 1, 5};
 - System.out.println("排序前: " + Arrays.toString(numbers));
 - MergeSort ms = new MergeSort();
 - ms.sort(numbers, 0, numbers.length - 1);
 - System.out.println("排序后: " + Arrays.toString(numbers));
 - }
 - public void sort(int[] numbers, int from, int to) {
 - int middle = (from + to) / 2;
 - if (from < to) {
 - sort(numbers, from, middle);
 - sort(numbers, middle + 1, to);
 - //左侧数列最大值小于右侧数列最小值, 不需要通过合并来调整顺序
 - if(numbers[middle] < numbers[middle + 1])
 - return;
 - merge(numbers, from, middle, to);
 - }
 - }
 - private void merge(int[] numbers, int from, int middle, int to) {
 - int[] temp = new int[to - from + 1];
 - int left = from;
 - int right = middle + 1;
 - int i = 0;
 - //从拆分到两边数列各剩一个数字开始合并; 当数列中有多个数字时, 一定是已经排好序的
 - //从两边数列左侧开始依次取数对比, 挑选小的一个放入临时数组
 - while (left <= middle && right <= to) {
 - if (numbers[left] < numbers[right]) {
 - temp[i++] = numbers[left++];
 - } else {
 - temp[i++] = numbers[right++];
 - }
 - }
 - //把左边数列剩余的数移入数组
 - while (left <= middle) {
 - temp[i++] = numbers[left++];
 - }
 - //把右边数列剩余的数移入数组
 - while (right <= to) {
 - temp[i++] = numbers[right++];
 - }
 - System.arraycopy(temp, 0, numbers, from, temp.length);
 - }
 - }
 
运行:
- 排序前: [4, 3, 6, 2, 7, 1, 5]
 - 排序后: [1, 2, 3, 4, 5, 6, 7]
 
合并排序平均情况和最坏情况的时间复杂度都是O(nlogn),因为需要额外的辅助空间,空间复杂度为O(n)。
Java与算法之(11) - 合并排序的更多相关文章
- 算法笔记_014:合并排序(Java)
		
1 问题描述 给定一组数据,使用合并排序得到这组数据的非降序排列. 2 解决方案 2.1 合并排序原理简介 引用自百度百科: 合并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Div ...
 - Java与算法之(10) - 希尔排序
		
希尔排序是插入排序的一种,是直接插入排序的改进版本. 对于上节介绍的直接插入排序法,如果数据原来就已经按要求的顺序排列,则在排序过程中不需要进行数据移动操作,即可得到有序数列.但是,如果最初的数据是按 ...
 - c++(合并排序)
		
前面一篇博客提到的快速排序是排序算法中的一种经典算法.和快速排序一样,合并排序是另外一种经常使用的排序算法.那么合并排序算法有什么不同呢?关键之处就体现在这个合并上面. 合并算法的基本步骤如下所 ...
 - java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述
		
算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. ...
 - 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)
		
排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...
 - Shell排序算法和合并排序算法
		
Shell排序(希尔排序)算法Shell排序严格来说基于插入排序的思想,其又称为希尔排序或者缩小增量排序. Shell排序的流程:1.将由n个元素的数组分成n/2个数字序列,第1个数据和第n/2+1个 ...
 - java讲讲几种常见的排序算法(二)
		
java讲讲几种常见的排序算法(二) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 堆排序 思路:构建一个小顶堆,小顶堆就是棵二叉树,他的左右孩子均大于他的根节点( ...
 - 用 Java 实现的八种常用排序算法
		
八种排序算法可以按照如图分类 交换排序 所谓交换,就是序列中任意两个元素进行比较,根据比较结果来交换各自在序列中的位置,以此达到排序的目的. 1. 冒泡排序 冒泡排序是一种简单的交换排序算法,以升序排 ...
 - 数据结构和算法 – 11.高级排序算法(上)
		
对现实中的排序问题,算法有七把利剑可以助你马道成功. 首先排序分为四种: 交换排序: 包括冒泡排序,快速排序. 选择排序: 包括直接选择排序,堆排序. 插入排序 ...
 
随机推荐
- 利用grep-console插件使Intellij idea显示多颜色调试日志
			
由于Intellij idea不支持显示ascii颜色,grep-console插件能很好的解决这个问题,下面就以开发JavaEE项目中,结合Log4j配置多颜色日志输出功能. 安装grep-cons ...
 - Eclipse中Spring插件的安装
			
java中为了方便学习使用SSH框架,框架插件的安装是非常必要的. 本博文记录了自己安装Spring插件的过程: 本机环境:win8 64bit eclipse版本:4.5.2 MARS 插件版本:S ...
 - ES6字符串方法
			
ES6字符串提供三个函数确定一个字符串是否包含在另一个字符串中,分别是includes().startsWith().endsWith(),这三种方法都返回一个布尔值. includes()方法表示是 ...
 - 基于CDH 5.9.1 搭建 Hive on Spark 及相关配置和调优
			
Hive默认使用的计算框架是MapReduce,在我们使用Hive的时候通过写SQL语句,Hive会自动将SQL语句转化成MapReduce作业去执行,但是MapReduce的执行速度远差与Spark ...
 - 每周.NET前沿技术文章摘要(2017-05-10)
			
汇总国内外.NET社区相关文章,覆盖.NET ,ASP.NET和Docker容器三个方面的内容: .NET Debugging .NET core with SOS everywhere 链接:htt ...
 - StringUtils工具类常用方法
			
前言:工作中看到项目组里的大牛写代码大量的用到了StringUtils工具类来做字符串的操作,便学习整理了一下,方便查阅. isEmpty(String str) 是否为空,空格字符为false is ...
 - C#又能出来装个B了。一步一步微信跳一跳自动外挂
			
PS:语言只是载体.思维逻辑才是王道 前天看见了个python的脚本.于是装python.配置环境变量.装pip.折腾了一上午,最终装逼失败. 于是进入博客园,顶部有篇文章吸引了我 .NET开发一个微 ...
 - 利用generator自动生成model(实体)、dao(接口)、mapper(映射)
			
1 在MySQL数据库中创建相应的表 /* Navicat MySQL Data Transfer Source Server : 虚拟机_zeus01 Source Server Version : ...
 - bzoj 4444: [Scoi2015]国旗计划
			
Description A国正在开展一项伟大的计划--国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这 项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名优秀的 ...
 - bzoj 4198: [Noi2015]荷马史诗
			
Description 追逐影子的人,自己就是影子. --荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由& ...