【排序算法】归并排序

零、写在前面

  • 活动地址:CSDN21天学习挑战赛
  • 本人蒟蒻一枚,文章若有不足之处请大家批评指出,欢迎大家留言。

一、排序算法

排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个关键字有序的序列。

二、归并排序 (Merge Sort)

 1. 介绍

归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治( divide
and conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案修补”在一起,即分而治之)。

  1.1 算法描述
  • 把长度为n的输入序列分成两个长度为n/2的子序列;
  • 对这两个子序列分别采用归并排序;
  • 将两个排序好的子序列合并成一个最终的排序序列。
  1.2 算法步骤

现在有一个数组 arr = [8, 3, 4, 7, 1, 6, 2, 5],将其排序。

  1. 我们先将数组划分成两个子数组
  2. 一直递归,把子数组划分成更小的子数组,直到子数组只有一个元素;
  3. 按照递归的返回顺序,不断合并排序好的子数组,直到整个数组有序。

在这里插入图片描述

  1.3 过程分析

如图所示实现划分
在这里插入图片描述

public static void mergeSort(int[] arr, int left, int right, int[] temp) {
    if (left < right) { 							//(1)
        int mid = (left + right) / 2; 				//(2)
        mergeSort(arr, left, mid, temp); 			//(3)
        mergeSort(arr, mid + 1, right, temp); 		//(4)
        merge(arr,left,mid,right,temp); 			//(5)
    }
}

(1)当 left 小于 right,说明元素个数大于1,将其划分成两个子数组
(2)位于中间元素索引
(3)左子数组
(4)右子数组
(5)合并左右子数组

合并过程,对最后一组分析,其他同理
(1)设置变量 i 指向有序左子数组第一个值的索引;j 右子数组索引t 存放合并后数组的索引
(2)比较 arr[i] 与 arr[j] 值的大小,数值小的放入 temp[t];
(3)左右子数组中数值小的索引加一, t++; 重复(2),直到 i 和 j 遍历完
在这里插入图片描述例如,本图 j 指向的值 小于 i 指向的,,j++,t++。
在这里插入图片描述

public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
	// (1)
    int i = left;
    int j = mid+1;
    int t = 0;
    while (i <= mid & j <= right) {
        if (arr[i] <= arr[j]) { // (2)(3)
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }else{
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }
    }
    
    while( i <= mid ) {//左子数组还有剩余的元素,就全部填充到temp
        temp[t] = arr[i];
        t += 1;
        i += 1;
    }
   while( j <= right ) {//右子数组还有剩余的元素,就全部填充到temp
        temp[t] = arr[j];
        t += 1;
        j += 1;
    }
   	//将temp数组的元素拷贝到arr
    t = 0;
    int tempLeft = left;
    while( tempLeft <= right ) {
        arr[tempLeft] = temp[t];
        t += 1;
        tempLeft +=1;
    }
}
  1.3 复杂度分析

归并排序是一种稳定的排序方法。归并排序的性能不受输入数据的影响,始终都是O(nlogn)的时间复杂度。

  • 时间复杂度:O(nlogn)。
  • 空间复杂度:O(n)。因为需要额外 n 大小的数组用于合并。
  1.4 完整代码
package drs.merge.sort;
import java.util.Arrays;
public class MergeSort {
	public static void main(String[] args) {
		int arr[] = {8,3,4,7,1,6,2,5};
		int temp[] = new int[arr.length];
		System.out.println("排序前数组:"+ Arrays.toString(arr));
		mergeSort(arr, 0, arr.length-1, temp);
		System.out.println("排序后数组:"+ Arrays.toString(arr));
	}

	public static void mergeSort(int[] arr, int left, int right, int[] temp) {
	    if (left < right) {
	        int mid = (left + right) / 2;
	        mergeSort(arr, left, mid, temp);
	        mergeSort(arr, mid + 1, right, temp);
	        merge(arr,left,mid,right,temp);
	        System.out.println("排序中数组:"+ Arrays.toString(arr));
	    } else {
	    	return;
		}
	}
	/**
	 *  @param  arr 排序的原始数组
	 *  @param left 左边有序序列的初始索引
	 *  @param mid 中间索引
	 *  @param right 右边索引
	 *  @param temp 做中转的数组
	 **/
	public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
	    int i = left;
	    int j = mid+1;
	    int t = 0;
	    while (i <= mid & j <= right) {
	        if (arr[i] <= arr[j]) {
	            temp[t] = arr[i];
	            t += 1;
	            i += 1;
	        }else{
	            temp[t] = arr[j];
	            t += 1;
	            j += 1;
	        }
	    }
	    while( i <= mid ) {
	        temp[t] = arr[i];
	        t += 1;
	        i += 1;
	    }
	    while( j <= right ) {
	        temp[t] = arr[j];
	        t += 1;
	        j += 1;
	    }
	    t = 0;
	    int tempLeft = left;
	    while( tempLeft <= right ) {
	        arr[tempLeft] = temp[t];
	        t += 1;
	        tempLeft +=1;
	    }
	}
}

运行结果:

排序前数组:[8, 3, 4, 7, 1, 6, 2, 5]
排序中数组:[3, 8, 4, 7, 1, 6, 2, 5]
排序中数组:[3, 8, 4, 7, 1, 6, 2, 5]
排序中数组:[3, 4, 7, 8, 1, 6, 2, 5]
排序中数组:[3, 4, 7, 8, 1, 6, 2, 5]
排序中数组:[3, 4, 7, 8, 1, 6, 2, 5]
排序中数组:[3, 4, 7, 8, 1, 2, 5, 6]
排序中数组:[1, 2, 3, 4, 5, 6, 7, 8]
排序后数组:[1, 2, 3, 4, 5, 6, 7, 8]

ps:参考资料

  1. 一头小山猪. 经典算法. https://blog.csdn.net/u012039040/category_10804722.html
  2. 一像素. 十大经典排序算法(动图演示). https://www.cnblogs.com/onepixel/p/7674659.html
  3. 菜鸟教程. 十大经典排序算法. https://www.runoob.com/w3cnote/merge-sort.html
  4. 一条为归的鱼. 归并排序. https://blog.csdn.net/weixin_45857153/article/details/110474615
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值