(Java)排序算法(五)——归并排序(Merge Sort)

归并排序(Merge Sort)

基本思想

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

算法描述

①把长度为n的输入序列分成两个长度为n/2的子序列;
②对这两个子序列分别采用归并排序;
③将两个排序好的子序列合并成一个最终的排序序列。

动图演示

在这里插入图片描述
在这里插入图片描述

代码实现

	public static int[] mergeSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return arr;
		}
		return mergeSort(arr, 0, arr.length - 1);
	}

	/**
	 * 功能描述:递归方法,分别对数组左右两侧进行归并排序
	 */
	public static int[] mergeSort(int[] arr, int l, int r) {
		if (l == r) {
			return arr;
		}
		//L和R的中点位置,(L+R)/2
		int mid = l + ((r - l) >> 1);
		//左侧排序
		mergeSort(arr, l, mid);
		//右侧排序
		mergeSort(arr, mid + 1, r);
		//整合
		return merge(arr, l, mid, r);
	}

	/**
	 * 功能描述:数组左右两部分排好序,进行整合
	 */
	public static int[] merge(int[] arr, int l, int m, int r) {
		//保持范围内数组个数一致  r - l + 1
		int[] help = new int[r - l + 1];
		int i = 0;
		//指针分别指向左右两侧的第一个数
		int p1 = l;
		int p2 = m + 1;
		//谁小填谁,跳出这个循环,有且只有一侧必定越界
		while (p1 <= m && p2 <= r) {
			//填完的数,到下一个位置+1
			help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
		}
		//两个循环走一个,将不越界的填进辅助数组
		while (p1 <= m) {
			help[i++] = arr[p1++];
		}
		while (p2 <= r) {
			help[i++] = arr[p2++];
		}
		//辅助数组拷贝给原数组
		for (i = 0; i < help.length; i++) {
			//保证传递给原数组是从l开始的
			arr[l + i] = help[i];
		}
		return arr;
	}

分析

稳定性

归并排序是稳定的。因为在使用额外空间的时候,靠前区域的元素只要小于等于靠后区域的元素就能被放进额外空间。

时间复杂度

任何情况下 T(n) = O(nlogn)。归并排序主要是靠递归加二分法,每一层的时间代价都是 n 相关,一共有 logn 层,所以时间复杂度是 n*logn。所以无论数组是不是有序的,都会被二分法分为前后两个部分,然后递归下去。

发布了52 篇原创文章 · 获赞 68 · 访问量 7138

猜你喜欢

转载自blog.csdn.net/qq_42937522/article/details/105128538
今日推荐