持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
作者平台:
| CSDN:blog.csdn.net/qq_4115394…
| 知乎:www.zhihu.com/people/1024…
| GitHub:github.com/JiangXia-10…
| 微信公众号:1024笔记
本文一共1812字,预计阅读8分钟
前言
前面几篇文章介绍了一些比较经典的排序算法,比如冒泡排序、插入排序、选择排序、希尔排序以及速度较快的快速排序,今天继续学习另一个比较常见并且速度仅次于快速排序的排序算法:归并排序算法。
什么是归并排序
归并排序(Merge Sort)的核心和快排比较类似,都是采用分治加递归的操作。归并排序是递归对待排序数组进行对半分组,然后首先从最小的分组开始进行比较排序, 然后再逐层进行归并操作合并成大的分组,从而实现最终的所有的元素都是有序的。其排序速度仅次于快速排序,时间复杂度为O(nlogn),但归并排序是一种稳定排序算法, 即采用归并排序算法之后相等元素的相对位置并不会发生改变。
比如有待排序数组{4 5 8 1 7 2 6 3},采用归并排序算法对其按照从大到小的顺序进行排序。
那么首先对其进行分层,中间点为(0+7)/2 = 3.5,选下标为4的位置,左边数组为4 5 8 1,右边数组为7 2 6 3,然后分别对左右两个数组拆分,左边拆分为两个4 5 和8 1,右边拆分为 7 2 和 6 3,然后再拆分,即上述长度为8的原始元素数组拆分为8个每个数组只有一个元素的独立数组。
如果上述的操作看成是从上到下拆分,则接下来是从下到上进行归并。4和5归并成一个数组4,5,8和1归并成一个数组1 8,再对归并合成的两个较大数组进行归并和排序,即又合成较大数组1 4 5 8。这是左边,右边同理,数组7和2归并比较成2,7,数组6和数组3归并成3,6,然后再归并排序成较大数组2,3,6,7.这样上述8个独立的小数组归并排序成了两个较大数组左边为1 4 5 8,右边为2 3 6 7,再对这两个数组进行归并和排序,最终合成为1 2 3 4 5 6 7 8有序数组。
归并排序的java实现
采用java代码实现如下:
package com.jiangxia.SortDemo;
public class MergeSort {
// 归并排序
public static int[] mergeSort(int[] number, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
// 先对左边进行归并排序
mergeSort(number, low, mid);
// 再对右边归并排序
mergeSort(number, mid + 1, high);
//对左右两边已经进行归并排序的有序数组进行合并
mergeArray(number, low, mid, high);
}
return number;
}
// 合并前面排序之后的两个有序数组
public static void mergeArray(int[] number, int low, int mid, int high) {
int[] temp = new int[high - low + 1];
int i = low;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= high) {
// 对比大小,调整顺序
if (number[i] < number[j]) {
temp[k++] = number[i++];
} else {
temp[k++] = number[j++];
}
}
// 右边剩余元素填充进temp中,因为前面已经归并,所以剩下的元素肯定小于右边剩余的元素)
while (i <= mid) {
temp[k++] = number[i++];
}
// 右边剩余元素填充进temp中,因为前面已经归并,所以剩下的元素肯定大于左边剩余的元素)
while (j <= high) {
temp[k++] = number[j++];
}
// 调整数组顺序
for (int x = 0; x < temp.length; x++) {
number[x + low] = temp[x];
}
}
// 测试算法
public static void main(String[] args) {
int[] number = {4,2,6,1,9,7,8,0,3,5};
System.out.println("归并排序之前:");
for (int i = 0; i < number.length; i++) {
System.out.print(number[i]+" ");
}
mergeSort(number,0,number.length-1);
System.out.println("\n归并排序之后:");
for (int i = 0; i < number.length; i++) {
System.out.print(number[i]+" ");
}
}
}
排序结果如下:
总结
归并排序的核心是分治和递归,通过递归操作对原始数组的拆分成尽可能小的数组,然后对小数组进行归并操作和比较排序,从而实现了最终元素的有序。归并排序和快排都是采用分治和递归的思想,但是归并排序的时间复杂度仅次于快速排序,并且归并排序是一种稳定排序,不会造成相等元素位置的变化。