排序算法七:归并排序

归并排序

归并排序(Merge Sort)同快速排序一样,同样是采用分治策略(Divide and Conquer)的一种较为快速的排序算法。它与快速排序的最大不同,也即其特点体现在快速排序是从大到小的层层分割,直到把每一部分分割到最小,而归并排序则是由小到大的层层合并,直到全部内容合并为一个整体。也因为这种关系,我把归并排序放在了快速排序的后面来写。

归并排序的实现思路为,首先将数组分割成最小的模块,连续的两块分别排序放置到一申请的临时数组空间上,临时的数组空间最后将排好序的内容复制到原数组上,实现一趟排序。数组中连续的两块比较方式为,分别依次比较两部分的小者往临时数组中放置,直到其中之一放置完毕,将另一没有放置完毕的数组剩余元素都放置到临时数组中,完成一次合并动作。完成一趟归并排序后,执行递归,并最终达到实现全部内容归并到一个数组为止。

下面是略作修改的百度百科Java代码(其思路和自己所想几乎一致,故拿来主义,也避免重复):

		/**
		 * <pre>
		 * 二路归并
		 * 原理:将两个有序表合并和一个有序表
		 * </pre>
		 * @param data
		 * @param firstStart
		 * 第一个有序表的起始下标
		 * @param secondStart
		 * 第二个有序表的起始下标
		 * @param secondEnd
		 * 第二个有序表的结束小标
		 * @return 
		 * */
		private static void merge(int[] data, int firstStart, int secondStart, int secondEnd) {
			//临时数组元素
			int[] tmp = new int[secondEnd - firstStart + 1];
			int i = firstStart, j = secondStart, k = 0;
			//将两个有序表中的元素按顺序放入临时数组,(事实上其中之一的元素必完全放入临时数组中)
			while (i < secondStart && j <= secondEnd) {
				if (data[i] <= data[j]) {
					tmp[k] = data[i];
					k++;
					i++;
				} else {
					tmp[k] = data[j];
					j++;
					k++;
				}
			}
			//如果第一个有序数组仍有元素剩余,将第一个有序数组的剩余元素全部放入临时数组
			while(i<secondStart){
				tmp[k]=data[i];
				i++;
				k++;
			}
			//如果第二个有序数组仍有元素剩余,将第二个有序数组的剩余元素全部放入临时数组
			while (j <= secondEnd) {
				tmp[k] = data[j];
				j++;
				k++;
			}
			//将临时数组中的元素都复制到原数组相应位置中
			System.arraycopy(tmp, 0, data, firstStart, tmp.length);
		}
		 
		/**
		 * 二路归并排序
		 * @param data:数据
		 * @param start:起点坐标
		 * @param width:每次归并的有序集合的宽度
		 */
		public static void mergeSort(int[] data, int start, int width) {
		int size = data.length;
		//可分成的两两的合并数据块的个数
		int mid = size / (width << 1);
		//取余数,判断是否数据是否已经整除
		int c = size & ((width << 1) - 1);
		// -------归并到只剩一个有序集合的时候结束算法-------//
		if (mid == 0)
		return;
		// ------进行一趟归并排序-------//
		for (int i = 0; i < mid; i++) {
		start = i * 2 * width;
		merge(data, start, start + width, (width << 1) + start - 1);
		}
		// -------将剩下的数和倒数一个有序集合归并-------//
		if (c != 0)
		merge(data, size - c - 2 * width, size - c, size - 1);
		// -------递归执行下一趟归并排序------//
		mergeSort(data, 0, 2 * width);
		}

毫无疑问这也是递归写法,其初始入参为要排序的入参data,起点坐标 0 ,起始有序队列的宽度 1,明显来看其代码写起来相较于快速排序已经复杂了不少。相对于快速排序,归并排序的在算法复杂度上和前者一致,但是速度上略慢,并且需要O(n)的空间复杂度,但是归并排序适合外部排序,无需一次将数据全部拿入内存来使用。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值