目录

一,归并排序简介

二,归并排序原理

三,归并排序图解

1,归并总体的图解

2,合并两个子组的流程

3,归并排序动画演示

四,归并排序代码实现与分析(Java)

1,方法的合集

2,Merge类各方法的解析

3,Merge类全部代码

4,测试和运行

五,总结


一,归并排序简介        

        归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

二,归并排序原理

1,先将一组数据尽可能拆分为两个元素相同的子组 ,直到拆分每个子组的元素为1。

2,将相邻的两个子组合并成一个有序的大组

3,不断重复步骤2,知道只剩下一个组为止

三,归并排序图解

1,归并总体的图解

先是采用“分”将数组分开,然后是“治”将其合并,如下图:

2,合并两个子组的流程

归并排序的核心部分就是这个“合并”的流程,下面附上一部分的图解:

在对子组排序中我们引入的三个指针,p1指向了左子组,p2指向了右子组,i指向辅助数组(用于存放排序好的数据)。

先将p1,p2位置的数据进行比较,较小者放入辅助数组中,并将i指针较小者的指针往前移一位,这便完成一次填充。

特殊情况:当有一个指针移到子组的末尾时,该指针则停止移动另外一个指针i指针继续移动。

3,归并排序动画演示

对于大部分来说动画一定是直观并且生动的,下面附上一段选自网上的归并排序算法,感受算法之美。

四,归并排序代码实现与分析(Java)

1,方法的合集

类名 Merge
构造方法 Merge()
成员方法
public static void sort(Comparable[] a);//对数组内元素进行排序
private static void sort(Comparable[] a,int low, int high);  //重载方法
private static void merge(Comparable[] a,int low, int mid, int high); //完成归并的关键方法
private static boolean less(Comparable v,Comparable w); //比较v元素是否小于v元素
成员变量
private static Comparable[] assist;

//完成归并操作的辅助数组

2,Merge类各方法的解析

(1)对数组内元素进行排序,sort方法:

//对数组内元素进行排序public static void sort(Comparable[] a){//初始化assistassist = new Comparable[a.length];//定义low和high分别表示最小和最大索引int low = 0;int high = a.length-1;//调用sort重载方法完成数组a中的low 到 high 的排序sort(a,low,high);}

(2)sort的重载方法,引入了数组的头尾索引:lowhigh

 //对数组a中 索引low 到 索引high 之间的元素进行排序private static void sort(Comparable[] a,int low, int high){//安全性校验 当high<=low时结束方法if (high<=low){return;}//将a数组low 到 high分为两组int mid = (high+low)/2;//分别对每一组数据进行排序 利用了重载方法sort(a,low,mid);sort(a,mid+1,high);//将两组数据进行归并merge(a,low,mid,high);}

方法中mid变量用于将数组分组。

(3)merge方法,用于归并子组,是该算法的核心部分:

    //将索引low到索引mid为一个子组,mid+1到high为另一个子组,将这两个子组合成为一个有序大组private static void merge(Comparable[] a,int low, int mid, int high){//定义3个指针 分别指向辅助数组assist两个子组int i = low;int p1 = low;int p2 = mid+1;//移动p1 p2 比较对应索引的值并加到辅助数组对应索引处while (p1<=mid && p2<=high){if (less(a[p1],a[p2])){assist[i++]=a[p1++];}else {assist[i++]=a[p2++];}}//p1没有走完while (p1<=mid){assist[i++]=a[p1++];}//p2没有走完while (p2<=high){assist[i++]=a[p2++];}//将排序好的assist数组的数据拷贝到数组a对应位置for (int index=low;index<=high;index++){a[index]=assist[index];}}

注:

(i)第一个while循环是两个指针都未到末尾移动的情况。

(ii)后二个while循环用于两个指针分别走到末尾的情况。

(iii) assist[i++]=a[p1++],表示将a[p1]的值赋给assist[i]并将两个指针往后移一位。

(4)less方法,比较两个元素大小,在方法merge中调用过

 //比较v元素是否小于w元素private static boolean less(Comparable v,Comparable w){return v.compareTo(w)<0;}

3,Merge类全部代码

public class Merge {//辅助数组private static Comparable[] assist;//对数组内元素进行排序public static void sort(Comparable[] a){//初始化assistassist = new Comparable[a.length];//定义low和high分别表示最小和最大索引int low = 0;int high = a.length-1;//调用sort重载方法完成数组a中的low 到 high 的排序sort(a,low,high);}//对数组a中 索引low 到 索引high 之间的元素进行排序private static void sort(Comparable[] a,int low, int high){//安全性校验 当high<=low时结束方法if (high<=low){return;}//将a数组low 到 high分为两组int mid = (low+high)/2;//分别对每一组数据进行排序sort(a,low,mid);sort(a,mid+1,high);//将两组数据进行归并merge(a,low,mid,high);}//将索引low到索引mid为一个子组,mid+1到high为另一个子组,将这两个子组合成为一个有序大组private static void merge(Comparable[] a,int low, int mid, int high){//定义3个指针 分别指向辅助数组assist两个子组int i = low;int p1 = low;int p2 = mid+1;//移动p1 p2 比较对应索引的值并加到辅助数组对应索引处while (p1<=mid && p2<=high){if (less(a[p1],a[p2])){assist[i++]=a[p1++];}else {assist[i++]=a[p2++];}}//p1没有走完while (p1<=mid){assist[i++]=a[p1++];}//p2没有走完while (p2<=high){assist[i++]=a[p2++];}//将排序好的assist数组的数据拷贝到数组a对应位置for (int index=low;index<=high;index++){a[index]=assist[index];}}//比较v元素是否小于w元素private static boolean less(Comparable v,Comparable w){return v.compareTo(w)<0;}
}

4,测试和运行

先创建一个测试类MergeTest:

import java.util.Arrays;public class MergeTest {public static void main(String[] args) {Integer[] a1 = {4,2,5,3,6,1,8,7};System.out.println("--------------a1排序前--------------");System.out.println(Arrays.toString(a1));Merge.sort(a1); //进行排序System.out.println("--------------a1排序后--------------");System.out.println(Arrays.toString(a1));Integer[] a2 = {5,6,3,1,8,7,2,4,10};System.out.println("--------------a2排序前--------------");System.out.println(Arrays.toString(a2));Merge.sort(a2); //进行排序System.out.println("--------------a2排序后--------------");System.out.println(Arrays.toString(a2));Integer[] a3 = {9,4,5,1,8,0,1,3,6};System.out.println("--------------a3排序前--------------");System.out.println(Arrays.toString(a3));Merge.sort(a3); //进行排序System.out.println("--------------a3排序后--------------");System.out.println(Arrays.toString(a3));}
}

运行结果:

五,总结

我们将归并排序中的“分”和“治”都独立成了方法,这样便于理解该算法的思想与实现,归并排序的核心就在“治”的地方,即merge方法的实现,其中有三个while循环用于表示三个指针移动的不同情况。

本文或许会有纰漏和错误之处,欢迎各位读者指出,希望大家在评论区多多友好讨论,喜欢文本的话给作者点个小小收藏和关注吧QAQ~

归并排序详解(Java语言描述 萌新向)相关推荐

  1. 详解 Java 17中的新特性:“密封类”

    作者:程序猿DD 博客:https://blog.didispace.com/ Java 17推出的新特性Sealed Classes经历了2个Preview版本(JDK 15中的JEP 360.JD ...

  2. 详解Java 8十大新特性

    前言: Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.在Java Code Geeks上已经有很多介绍Java 8新特性的文章,例如Playing with Java ...

  3. N皇后问题的解(洛谷P1219题题解,Java语言描述)

    题目要求 P1219题目链接 分析 <N皇后问题的解决方案--Java版> N皇后问题就是一个DFS算法问题,照着基本把代码cp进去,就T了最后一个点: 当时有事,我就不想优化算法了,于是 ...

  4. 归并排序过程实现c语言,C语言归并排序详解

    C语言归并排序详解 发布日期:2015-12-31 11:16 来源: 标签: 编程语言 C教程 C语言归并排序 C语言归并排序算法 本章我们主要学习C语言实现排序算法之归并排序,对归并排序的原理及实 ...

  5. 去重的Set解不出“斯诺登的密码”(洛谷P1603题题解,Java语言描述)

    题目要求 P1603题目链接 分析 我们不如直接获取其平方数,这个就要基于HashMap啦,提前指定一下初始长度! 像10啊,20啊这种模完只剩00的,就不要了吧(他说是要最小的结果,开头0要去掉,那 ...

  6. 打表巧解蛇形方阵(洛谷P5731题题解,Java语言描述)

    题目要求 题目链接 分析 这题固然可以分析归纳,但既然是不大于9的规模,而且复杂度很低,不如--打表? 表自己手算就知道了,很好处理. AC代码(Java语言描述) import java.util. ...

  7. 互逆的压缩与解压(洛谷P1319、P1320题题解,Java语言描述)

    P1319题目要求 P1319题目链接 P1320题目要求 P1320题目链接 分析 这两个题啊,就是互逆过程嘛-- 说白了就是统计0与1,将一个0-1点阵压缩为一串数值或者将一串数值复原为一个0-1 ...

  8. 动态规划求解限时采药问题(洛谷P1048题题解,Java语言描述)

    题目要求 P1048题目链接 分析 荐读:大神博文 -> <聊聊动态规划与记忆化搜索> 这题就是一个标准的DP水题,对于不会DP的萌新,太难了!对于整天搞DP的算法大佬,水爆了! 荐 ...

  9. java 死锁 内存消耗_详解Java中synchronized关键字的死锁和内存占用问题

    先看一段synchronized 的详解: synchronized 是 java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并 ...

最新文章

  1. mysql配置文件构成以及具体的配置demo
  2. beego 使用github.com/astaxie/beego/session异常问题
  3. spring下jndi配置
  4. 职业中专计算机基础试讲课,职业中专计算机基础教育分析
  5. Vue入门 ---- 仿百度搜索
  6. Spring Cloud 服务安全连接 1
  7. 车牌识别opencv_基于OpenCV 的车牌识别
  8. 分享选书原则,推荐几本书(附书评)
  9. 单片机喇叭如何响出报警声音 C语言程序,单片机报警器声音产生的方法(报警声音)...
  10. Java开发中的命名规范
  11. 程序员不要总想着四两拨千斤
  12. 餐厅扫码点餐怎么弄的(餐厅二维码自助点餐系统开发制作价格)
  13. P2150 [NOI2015]寿司晚宴
  14. Testing WLW!!
  15. Windows批处理文件*.bat
  16. 计算机中线性结构定义,数据结构基本概念
  17. 论文笔记 | Determinants of Cross-Border Mergers and Acquisitions
  18. 安居客新建表必须回答DBA的5个问题(DBRT规范)
  19. 【英语】-11月英语总结
  20. 万家杨柳青烟里:B+、B- 树的应用场景

热门文章

  1. 1.综合能源系统优化运行(碳交易机制下考虑需求响应的综合能源系统优化运行)
  2. 开学!可怕的日本,无情到令人感到恐惧!
  3. TCP与UDP的原理
  4. yum一次性下载安装包及其依赖包
  5. js中onchange事件举例用法
  6. 任天堂官宣塞尔达传说新作:为新产品护航?
  7. 如何给码农的Mac开光
  8. 【每日早报】2019/07/01
  9. Python Flask-Web学习中的坑坑洼洼
  10. YOLOV5通道剪枝【附代码】