排序算法(8): 归并排序(Merge Sort)

543 阅读1分钟

基本思想

归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;

算法描述

  • 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  • 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  • 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  • 重复步骤3直到某一指针到达序列尾
  • 将另一序列剩下的所有元素直接复制到合并序列尾

演示

代码实现

	public static void sort(int[] array, int l, int r, int[] tempArray) {
		if (l < r) {
			int mid = (l + r) / 2;
			sort(array, l, mid, tempArray);
			sort(array, mid + 1, r, tempArray);
			merge(array, l, mid, r, tempArray);
		}
	}

	/**
	 * 
	 * @param array     待排序数组
	 * @param left      待排序数组最左端下标
	 * @param mid
	 * @param right     待排序数组最右端下标
	 * @param tempArray 临时数组
	 */
	public static void merge(int[] array, int left, int mid, int right, int[] tempArray) {
		int l = left;
		int r = mid + 1;
		int t = 0;// tempArray填充数据的坐标
		
		//比较大小将比较小的数据放到tempArray中
		while (l <= mid && r <= right) {
			if (array[l] <= array[r]) {
				tempArray[t] = array[l];
				t = t + 1;
				l = l + 1;
			} else {
				tempArray[t] = array[r];
				t = t + 1;
				r = r + 1;
			}
		}
        //将不需要比较的直接复制到tempArray中
		while (l <= mid) {
			tempArray[t] = array[l];
			t = t + 1;
			l = l + 1;
		}
		while (r <= right) {
			tempArray[t] = array[r];
			t = t + 1;
			r = r + 1;
		}

		//将tempArray中的数据复制到array中
		int k = 0;
		for (int i = left; i <= right; i++) {
			array[i] = tempArray[k];
			k++;
		}
	}

时间复杂度

归并排序每次会把当前的序列一分为二,然后两部分各自排好序之后再合并,这个就像是一颗二叉树,每一层总的计算量是O(n)的,总的层数是O(logn)的,所以总的复杂度是O(nlogn)
最佳情况:O(nlogn)
最坏情况:O(nlogn)
平均情况:O(nlogn)

空间复杂度

需要与待排序元素同样大小的空间用于临时存放数据,所以空间复杂度是O(n)

优点与缺点

  • 对两个已有序的序列归并,优势明显,时间复杂度都是O(nlog2n)
  • 不适用于数据节点数据量大的数据

测试记录

待补充

源码

java.util.Arrays中使用到了归并排序