当前位置:   article > 正文

归并排序详解(Java语言描述 萌新向)_java归并排序

java归并排序

目录

一,归并排序简介        

二,归并排序原理

三,归并排序图解

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方法:

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

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

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

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

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

  1. //将索引low到索引mid为一个子组,mid+1到high为另一个子组,将这两个子组合成为一个有序大组
  2. private static void merge(Comparable[] a,int low, int mid, int high){
  3. //定义3个指针 分别指向辅助数组assist两个子组
  4. int i = low;
  5. int p1 = low;
  6. int p2 = mid+1;
  7. //移动p1 p2 比较对应索引的值并加到辅助数组对应索引处
  8. while (p1<=mid && p2<=high){
  9. if (less(a[p1],a[p2])){
  10. assist[i++]=a[p1++];
  11. }else {
  12. assist[i++]=a[p2++];
  13. }
  14. }
  15. //p1没有走完
  16. while (p1<=mid){
  17. assist[i++]=a[p1++];
  18. }
  19. //p2没有走完
  20. while (p2<=high){
  21. assist[i++]=a[p2++];
  22. }
  23. //将排序好的assist数组的数据拷贝到数组a对应位置
  24. for (int index=low;index<=high;index++){
  25. a[index]=assist[index];
  26. }
  27. }

注:

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

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

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

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

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

3,Merge类全部代码

  1. public class Merge {
  2. //辅助数组
  3. private static Comparable[] assist;
  4. //对数组内元素进行排序
  5. public static void sort(Comparable[] a){
  6. //初始化assist
  7. assist = new Comparable[a.length];
  8. //定义low和high分别表示最小和最大索引
  9. int low = 0;
  10. int high = a.length-1;
  11. //调用sort重载方法完成数组a中的low 到 high 的排序
  12. sort(a,low,high);
  13. }
  14. //对数组a中 索引low 到 索引high 之间的元素进行排序
  15. private static void sort(Comparable[] a,int low, int high){
  16. //安全性校验 当high<=low时结束方法
  17. if (high<=low){
  18. return;
  19. }
  20. //将a数组low 到 high分为两组
  21. int mid = (low+high)/2;
  22. //分别对每一组数据进行排序
  23. sort(a,low,mid);
  24. sort(a,mid+1,high);
  25. //将两组数据进行归并
  26. merge(a,low,mid,high);
  27. }
  28. //将索引low到索引mid为一个子组,mid+1到high为另一个子组,将这两个子组合成为一个有序大组
  29. private static void merge(Comparable[] a,int low, int mid, int high){
  30. //定义3个指针 分别指向辅助数组assist两个子组
  31. int i = low;
  32. int p1 = low;
  33. int p2 = mid+1;
  34. //移动p1 p2 比较对应索引的值并加到辅助数组对应索引处
  35. while (p1<=mid && p2<=high){
  36. if (less(a[p1],a[p2])){
  37. assist[i++]=a[p1++];
  38. }else {
  39. assist[i++]=a[p2++];
  40. }
  41. }
  42. //p1没有走完
  43. while (p1<=mid){
  44. assist[i++]=a[p1++];
  45. }
  46. //p2没有走完
  47. while (p2<=high){
  48. assist[i++]=a[p2++];
  49. }
  50. //将排序好的assist数组的数据拷贝到数组a对应位置
  51. for (int index=low;index<=high;index++){
  52. a[index]=assist[index];
  53. }
  54. }
  55. //比较v元素是否小于w元素
  56. private static boolean less(Comparable v,Comparable w){
  57. return v.compareTo(w)<0;
  58. }
  59. }

4,测试和运行

先创建一个测试类MergeTest:

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

运行结果:

五,总结 

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/67026
推荐阅读
相关标签
  

闽ICP备14008679号