归并排序

      归并排序是利用归并的思想实现排序,这里只介绍2路归并排序,其思想是:假设初始待排序队列记录数为n,看成n个长度为1的子序列,然后两两合并,得到个长度为2或1的有序子序列,再两两合并,……, 如此重复直至得到长度为n的有序序列为止。示意图如下。

        实现2路归并排序需要额外的与待排序序列大小相同的空间。给出两个有序子序列合并的代码:

	/**
	 * 两个有序序列的归并函数
	 * 
	 * @Title: merge
	 * @Description: 将有序的array[begin,...mid]与
	 *               array[mid+1,...,end]归并为assist[begin,...,end],最后复制到array
	 * @param array
	 * 				待排序数组
	 * @param assist
	 * 				辅助数据
	 * @param begin           array    [begin--------------mid--------------end]
	 * 	                    |      |        有序         |      有序       |
	 * @param mid               |
	 * 		            |            
	 * @param end             assist   [--------------------------------------]
	 *                                 |             有序                     |
	 */
	private void merge(int[] array, int[] assist, int begin, int mid, int end)
	{
		int i, j, k;
		for (i = begin, j = mid + 1, k = begin; (i < mid + 1) && (j <= end); k++)
		{
			if (array[i] < array[j])
			{
				assist[k] = array[i++];
			} else
			{
				assist[k] = array[j++];
			}
		}

		if (i < mid + 1) 
		{
			for (; i < mid + 1;)
			{
				assist[k++] = array[i++];
			}
		}

		if (j <= end)
		{
			for (; j <= end;)
			{
				assist[k++] = array[j++];
			}
		}

		// copy
		System.arraycopy(assist, begin, array, begin, (end - begin + 1));
	}
       归并排序的递归实现:

	/**
	 * 归并排序的实现
	 * 
	 * @Title: mSort
	 * @Description: array借助于assist把下标从begin到end的序列进行归并排序
	 * @param array
	 *            待排序序列
	 * @param assist
	 *            辅助序列
	 * @param begin
	 *            起始下标
	 * @param end
	 *            结束下标
	 */
	private void mSort(int[] array, int[] assist, int begin, int end)
	{
		int mid;
		if (begin == end)
		{
			return;
		} else
		{
			mid = (begin + end) / 2;
			mSort(array, assist, begin, mid);
			mSort(array, assist, mid + 1, end);
			merge(array, assist, begin, mid, end);
		}
	}
	/**
	 * 归并排序的主函数
	 * 
	 * @Title: mergeSort
	 * @Description: 给定待排序数组进行归并排序
	 * @param array
	 *            给定待排序数组
	 */
	public void mergeSort(int[] array)
	{
		// assist array
		int[] assist = new int[array.length];
		// sort
		mSort(array, assist, 0, array.length - 1);
	}

        非递归实现,其核心思想就是如图所示,第一轮子序列长度为1进行归并,第二轮子序列长度为2进行归并,第三轮子序列长度为4进行归并,····,直至子序列长度大于待排序列的长度。每一轮归并后,剩余序列,分两种情况:1、剩余序列大于当前子序列,则表明剩余有两个序列,进行归并;2、剩余序列小于当前子序列(包括0),则不进行操作。代码如下:

	/**
	 * 进行一趟归并排序
	 * 
	 * @Title: mergePass
	 * @Description: 子序列长度为k,对array序列进行一趟归并操作。
	 * @param array
	 *            待排序序列
	 * @param assist
	 *            辅助序列
	 * @param k
	 *            子序列长度
	 */
	private void mergePass(int[] array, int[] assist, int k)
	{
		int index = 0;
		while (index < array.length - 2 * k + 1)
		{
			merge(array, assist, index, (index + k - 1), (index + 2 * k - 1));
			index += 2 * k;
		}

		if (index < array.length - k)
		{
			merge(array, assist, index, (index + k - 1), array.length - 1);
		}
	}

/**
	 * 归并排序非递归实现
	 * 
	 * @Title: mergeSortNonRec
	 * @Description: 待排序序列array归并排序的非递归操作
	 * @param array
	 *            待排序序列
	 */
	public void mergeSortNonRec(int[] array)
	{
		// assist
		int[] assist = new int[array.length];
		// sort
		int k = 1;
		while (k < array.length)
		{
			mergePass(array, assist, k);
			k *= 2;
		}
	}

      性能分析:

       归并排序是一种稳定的排序算法,每趟归并需要所有记录扫描一遍,耗时O(n)时间,而由完全二叉树深度可知,整个归并排序需要进行次,因此总的时间复杂度为

O(nlogn)。非递归实现时归并排序需要与待排序数组相同的存储空间,递归实现除了上述存储空间,还需要深度为的栈。而且归并排序平均情况、最好情况和最坏情况的时间复杂度都为

         所以,归并排序是一种比较占用内存,但却效率高且稳定的排序算法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值