博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java与算法之(11) - 合并排序
阅读量:4708 次
发布时间:2019-06-10

本文共 1881 字,大约阅读时间需要 6 分钟。

天下事,合久必分,分久必合。合并排序的基本思想正是先分再合。

例如对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为例,完整的排序过程如下图:

来看代码:

 

[java]   
 
 
  1. import java.util.Arrays;  
  2.   
  3. /** 
  4.  * 合并排序法 
  5.  * Created by autfish on 2016/9/20. 
  6.  */  
  7. public class MergeSort {  
  8.   
  9.     public static void main(String[] args) {  
  10.         int[] numbers = new int[] {
    4, 3, 6, 2, 7, 1, 5};  
  11.         System.out.println("排序前: " + Arrays.toString(numbers));  
  12.   
  13.         MergeSort ms = new MergeSort();  
  14.         ms.sort(numbers, 0, numbers.length - 1);  
  15.   
  16.         System.out.println("排序后: " + Arrays.toString(numbers));  
  17.     }  
  18.   
  19.     public void sort(int[] numbers, int from, int to) {  
  20.         int middle = (from + to) / 2;  
  21.         if (from < to) {  
  22.             sort(numbers, from, middle);  
  23.             sort(numbers, middle + 1, to);  
  24.             //左侧数列最大值小于右侧数列最小值, 不需要通过合并来调整顺序  
  25.             if(numbers[middle] < numbers[middle + 1])  
  26.                 return;  
  27.             merge(numbers, from, middle, to);  
  28.         }  
  29.     }  
  30.   
  31.     private void merge(int[] numbers, int from, int middle, int to) {  
  32.         int[] temp = new int[to - from + 1];  
  33.         int left = from;  
  34.         int right = middle + 1;  
  35.         int i = 0;  
  36.   
  37.         //从拆分到两边数列各剩一个数字开始合并; 当数列中有多个数字时, 一定是已经排好序的  
  38.         //从两边数列左侧开始依次取数对比, 挑选小的一个放入临时数组  
  39.         while (left <= middle && right <= to) {  
  40.             if (numbers[left] < numbers[right]) {  
  41.                 temp[i++] = numbers[left++];  
  42.             } else {  
  43.                 temp[i++] = numbers[right++];  
  44.             }  
  45.         }  
  46.   
  47.         //把左边数列剩余的数移入数组  
  48.         while (left <= middle) {  
  49.             temp[i++] = numbers[left++];  
  50.         }  
  51.   
  52.         //把右边数列剩余的数移入数组  
  53.         while (right <= to) {  
  54.             temp[i++] = numbers[right++];  
  55.         }  
  56.   
  57.         System.arraycopy(temp, 0, numbers, from, temp.length);  
  58.     }  
  59. }  

运行:

 

 

[java]   
 
 
  1. 排序前: [4, 3, 6, 2, 7, 1, 5]  
  2. 排序后: [1, 2, 3, 4, 5, 6, 7]  

合并排序平均情况和最坏情况的时间复杂度都是O(nlogn),因为需要额外的辅助空间,空间复杂度为O(n)。

转载于:https://www.cnblogs.com/sa-dan/p/6837086.html

你可能感兴趣的文章
spring boot 错误处理之深度历险
查看>>
MySQL对于有大量重复数据表的处理方法
查看>>
Android应用开发学习笔记之多线程与Handler消息处理机制
查看>>
ubuntu 设置环境变量
查看>>
JSTL详解(一)
查看>>
Manacher 算法
查看>>
Linux磁盘及文件系统(三)Linux文件系统
查看>>
SDWebImage源码阅读(二)NSData+ImageContentType
查看>>
别在最好的年纪辜负最好的自己
查看>>
微软品牌形象广告 不是一般的优秀
查看>>
【Object.prototype.toString.call()】---判断某个对象属于哪种内置类型------【巷子】...
查看>>
转载:结构体的字节对齐
查看>>
用github来展示你的前端页面吧
查看>>
内存池
查看>>
SQLServer到底支持多少连接数的并发?
查看>>
深入分析java中文乱码问题
查看>>
Nginx(二)
查看>>
CF #329 D
查看>>
Android中pendingIntent的深入理解
查看>>
地图之CLLocationManager的使用 定位功能使用
查看>>