归并排序算法详解
Posted Dream_it_possible!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序算法详解相关的知识,希望对你有一定的参考价值。
归并排序采用递归+分治排序的思想,将有序在子序列进行合并。快速排序是采用递归+独立排序的思想,在时间复杂度和空间复杂度要比快速排序差点。
归并排序的思想: 一个数列中的任意一个长度大于1的子数列都可以分为2个长度差不都的序列,每次将这2个序列进行比较,然后将结果放入到新队列里进行返回。由于每次分割的操作都是均分,因此直到均分成后得到的子数列中只有一个元素时,进行排序完后,相当于排序完毕。也就是递归结束。
缺点: 比较占用内存,因为每次需要新的数组去接收左右数组排序后的结果。
完整代码:
package sort;
import java.util.Arrays;
/**
* @decription:
* @author: zhengbing.zhang
* @date: 2021/7/23 14:54
* 分治算法之归并排序:
* 将一个数组分为有序的几个数列,然后将已有序的子序列进行合并,然后对每个数列进行排序。
* 即先使每个子序列有序,再使子序列间有序。
* 设有数列: {6,202,100,301,38,8,1}
* 工作原理:
* 1. 申请工作空间,大小为存放2个大小已经排序序列之和。
* 2. 设置2个指针,最初为位置为两个已经排序序列的起始位置。
* 3. 比较两个指针所指的元素,选择相对较小的放入到合并空间里,并指针移到下一个位置。
* 4. 重复步骤3,直到有一个序列超出表尾。
* 5. 将另一个有序剩下的所有元素直接复制到合并空间的表尾。
* <p>
* 类似问题: 将2个升序链表合并。
* 归并排序的空间复杂度问题: 需要额外的空间存放每次排序后的2个子序列。
*/
public class MergeSort {
public static int[] mergeSort(int[] nums, int l, int h) {
if (l == h) {
return new int[]{nums[l]};
}
// 如果stackoverflow,检查临界值是否异常
int mid = l + (h - l) / 2;
// 左序数组
int[] leftArray = mergeSort(nums, l, mid);
// 有序数组
int[] rightArray = mergeSort(nums, mid + 1, h);
int[] newNum = new int[leftArray.length + rightArray.length];
int m = 0, i = 0, j = 0;
while (i < leftArray.length && j < rightArray.length) {
newNum[m++] = leftArray[i] < rightArray[j] ? leftArray[i++] : rightArray[j++];
}
while (i < leftArray.length) {
newNum[m++] = leftArray[i++];
}
while (j < rightArray.length) {
newNum[m++] = rightArray[j++];
}
return newNum;
}
public static void main(String[] args) {
int[] nums = new int[]{3,8, 9, 6, 5, 4, 8, 2, 1};
int[] newNums = mergeSort(nums, 0, nums.length - 1);
System.out.println(Arrays.toString(newNums));
}
}
打印结果:
归并排序的算法平均时间复杂度: O(nlogn),空间复杂度T(n)。
以上是关于归并排序算法详解的主要内容,如果未能解决你的问题,请参考以下文章
九种经典排序算法详解(冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序,计数排序,桶排序,基数排序)
经典排序算法和python详解:归并排序快速排序堆排序计数排序桶排序和基数排序