排序-----归并排序

归并排序(MergeSort)

定义:

        将数组分为两半,分别对这两半进行排序,然后将它们合并为一个有序的数组

        该算法采用分治(divide and conquer)策略。(divide)将问题成小块,治(conquer)是指攻克每个小块以达成解决方案。

具体:

1.将一个乱序的数组按mid值分为两个数组(新建一个数组用于存储顺序元素)。

2.将一个数组中的项与另一个数组中的项进行比较,将较小的项复制到新的第三个数组中。

3.当到达一个数组的末尾后,将另一个数组的剩余元素复制到新的第三个数组中。


如图:

            


import java.util.Arrays;

public class MergeSort {
	public static <T extends Comparable<? super T>> void mergeSort(T[] a, int first, int last) {
		// 先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
		T[] tempArray = (T[]) new Comparable[a.length];
		mergeSort(a, tempArray, first, last);

	}

	private static <T extends Comparable<? super T>> void mergeSort(T[] a, T[] tempArray, int first, int last) {
		
		if (first >= last)
			return;
		else {
			int mid = (first + last) / 2;
			//左边归并排序,使得左子序列有序
			mergeSort(a, tempArray, first, mid);
			//右边归并排序,使得右子序列有序
			mergeSort(a, tempArray, mid + 1, last);
			//将两个有序子序列合并
			merge(a, tempArray, first, mid, last);
		}
	}

	private static <T extends Comparable<? super T>> void merge(T[] a, T[] tempArray, int first, int mid, int last) {
		// 合并相邻子数组,a[first...mind]和a[mid+1...last]
		int beginHalf1 = first;
		int endHalf1 = mid;
		int beginHalf2 = mid + 1;
		int endHalf2 = last;
		// tempArray中下一个可用的位置
		int index = 0;
		while ((beginHalf1 <=endHalf1) && (beginHalf2 <= endHalf2)) {
			if (a[beginHalf1].compareTo(a[beginHalf2]) <=0) {
				tempArray[index++] = a[beginHalf1++];
			} else {
				tempArray[index++] = a[beginHalf2++];
			}
		}
		//将剩余项复制到tempArray中
		while(beginHalf1 <=endHalf1) {
			tempArray[index++]=a[beginHalf1++];
		}
		while(beginHalf2<beginHalf2) {
			tempArray[index++]=a[beginHalf2++];
		}
		//将tempArray中的项复制到数组a中
		for (int i = 0; i < index; i++)  
	        a[first+i] = tempArray[i];  
	}

	public static void main(String[] args) {
		Integer[] a = { 45, 83, 72, 56, 95, 4, 3, 2,0,34,23,42,423, 1 };
		MergeSort.mergeSort(a, 0, a.length-1);
		System.out.println(Arrays.toString(a));

	}
}

注意:

    mergeSort将数组分为两半,然后递归的将每一半再分为两半,直到每一项只包含一项时为止。此时开始合并步骤,将一对含一项的子段合并为含有两项的子段,一对含两项的子段合并为含四项的子段,以此类推。用mergeSort与调用merge是交织在一起的,真正的排序是发生在合并步骤而不是发生在递归调用步骤。

扫描二维码关注公众号,回复: 1658357 查看本文章


归并排序的效率:

        不管数组的初始状态如何,归并排序在最坏,最优,以及平均情形下都是O(nlogn)的。

        唯一缺点:需要一个临时数组。


猜你喜欢

转载自blog.csdn.net/qq_41304534/article/details/80726068