Java 归并排序算法
Posted 曾淘
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 归并排序算法相关的知识,希望对你有一定的参考价值。
简介
上一章我们学习了 Java 快速排序算法,这一章,我们来学习快归并排序算法,so,多了不说,继续老规矩,学习内容如下:
1、归并排序的定义
2、归并排序的思路
3、代码实现
4、运行过程 & 代码分析
1、归并排序的定义
归并排序:是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and
Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。
2、归并排序的思路
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
这里借助一个图 此图为借鉴,自己懒得画,如有侵权,请联系我处理! 作为说明:假设数组源为,84571362
3、代码实现
package com.gongchao.boss;
import java.util.Arrays;
/**
* description: 归并排序方法
* auth: zengtao
* time: 2020-12-23 16:45
**/
public class Main
public static void main(String[] args)
int array[] = 6, 5, 2, 7, 4, 3, 8, 12, 4, 9;
// 归并排序方法
System.out.println("排序前:" + Arrays.toString(array));
mergeSoft(array, 0, array.length - 1);
System.out.println("排序后:" + Arrays.toString(array));
// 归并
private static void mergeSoft(int[] arr, int low, int high)
int middle = (high + low) / 2;
//递归,直到low==high,也就是数组已不能再分了,
if (low < high)
// 左数组排序
mergeSoft(arr, low, middle);
// 右数组排序
mergeSoft(arr, middle + 1, high);
// 当数组不能再分,开始归并排序
merge(arr, low, middle, high);
/**
* 合并数据
*
* @param arr 数组
* @param low 开始位置
* @param middle 中间位置
* @param high 结束位置
*/
private static void merge(int[] arr, int low, int middle, int high)
// 临时数组,用于存储arr数据
int[] tempArr = new int[high - low + 1];
// 第一个数组的开始下标
int i = low;
// 第二个数组的开始下标
int j = middle + 1;
// 临时数组的下标,默认为0开始
int index = 0;
// 比较两个数组中的数据,然后存储
while (i <= middle && j <= high)
// 两个数组第一个数据比较,把小的数组放入数组中,临时数组下标和数组小/大的下标移动
if (arr[i] <= arr[j])
tempArr[index++] = arr[i++];
else
tempArr[index++] = arr[j++];
// 上面数据对比之后,数据1数据还有剩余
// 数组1【6, 5, 2, 7, 4, 3, 8】,数组2【12, 4, 9】,那么,数组1数据>数组2数据,
if (i <= middle)
// 只剩数组1数据,都是有序数据,所以数据直接放入临时数组
tempArr[index++] = arr[i++];
// 上面数据对比之后,数据2数据还有剩余
// 数组1【6, 5, 2, 7】,数组2【4, 3, 8,12, 4, 9】,那么,数组1数据< 数组2数据,
if (j <= high)
// 只剩数组2数据,都是有序数据,所以数据直接放入临时数组
tempArr[index++] = arr[j++];
System.out.println(" 排序中:" + Arrays.toString(arr));
// 重新临时数组中的数据,放入原数组中
for (int k = 0; k < index; k++)
arr[k + low] = tempArr[k];
运行结果
根据运行结果:这样我们就是实现了归并排序
4、运行过程 & 代码分析
为什么要写这个呢?
之前有些同学私信我,有些局部代码看起来还是有些吃力,感觉自己便携代码有点抓不住。
所以,这个也是针对这些同学,我一点一点的说明,方便同学更加方便理解。
一:首先我们先按照排序的思路来看
把长度为n的输入序列分成两个长度为n/2的子序列;
对这两个子序列分别采用归并排序;
分析
- 长度为n的输入序列------> 输入数组arr[]
- 输入数组,分为长度为n/2的数组------> 第1⃣️个开始位置到结束,第2⃣️个开始位置(第一个结束位置)到整个数组结束
- 对这两个子序列分别采用归并排序 -----> 方法中有归并,第1⃣️个归并,第2⃣️个归并
那么方法和参数就如约而来了,代码如下:
// 归并
private static void mergeSoft(int[] arr, int low, int high)
int middle = (high + low) / 2;
//递归,直到low==high,也就是数组已不能再分了,
if (low < high)
// 左数组排序
mergeSoft(arr, low, middle);
// 右数组排序
mergeSoft(arr, middle + 1, high);
// 当数组不能再分,开始归并排序
merge(arr, low, middle, high);
二:其次我们看最后一个思路
将两个排序好的子序列,合并成一个最终的排序序列。
那么就会有一个最终的具体的合并排序方法,内部原理如下
- 1.将数组分类2个,那么分别有2个,各自的start位置+结束位置
private static void merge(int[] arr, int low, int middle, int high)
- 2.分别将2个数组对比,大数组的放在一边,小的数据放在一边
// 临时数组,用于存储arr数据
int[] tempArr = new int[high - low + 1];
// 第一个数组的开始下标
int i = low;
// 第二个数组的开始下标
int j = middle + 1;
// 临时数组的下标,默认为0开始
int index = 0;
// 比较两个数组中的数据,然后存储
while (i <= middle && j <= high)
// 两个数组第一个数据比较,把小的数组放入数组中,临时数组下标和数组小/大的下标移动
if (arr[i] <= arr[j])
tempArr[index++] = arr[i++];
else
tempArr[index++] = arr[j++];
- 3.若:数组1vs数组2,数组1数据多,那么继续处理数组1,此为有序排序,若:数组1vs数组2,数组2多,那么继续处理数组2
// 上面数据对比之后,数据1数据还有剩余
// 数组1【6, 5, 2, 7, 4, 3, 8】,数组2【12, 4, 9】,那么,数组1数据>数组2数据,
if (i <= middle)
// 只剩数组1数据,都是有序数据,所以数据直接放入临时数组
tempArr[index++] = arr[i++];
// 上面数据对比之后,数据2数据还有剩余
// 数组1【6, 5, 2, 7】,数组2【4, 3, 8,12, 4, 9】,那么,数组1数据< 数组2数据,
if (j <= high)
// 只剩数组2数据,都是有序数据,所以数据直接放入临时数组
tempArr[index++] = arr[j++];
- 4.将最终数据返回给原数组
// 重新临时数组中的数据,放入原数组中
for (int k = 0; k < index; k++)
arr[k + low] = tempArr[k];
到此为止
代码具体解析,都已一一说明,希望对同学们有用。
谢谢观看,Thanks!
以上是关于Java 归并排序算法的主要内容,如果未能解决你的问题,请参考以下文章