算法 之 分治 - 合并排序-合并两个已排序的表

假定有一个数组 A[1...n],low, middle, high 为它的三个索引,并有 1 ≤ low ≤ middle < high ≤ n,使得两个子数组 A[low...middle],A[middle+1...high] 各自按升序排列。

我们要重新排列A中元素的位置,使得 A[low...high] 中的元素也按升序排列。这就是合并 A[low...middle] 和 A[middle+1...high] 的过程。

 

举个例子,就是我们有个数组 A = { 0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 }; 这里 low=0, middle=5, high=10

我们要对它进行排序使 A = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 

我们可以使用这样的方法来合并这两个子数组:

首先使用两个索引 s 和 t,初始化时各自指向 A[low] 和 A[middle+1],再用一个空数组 B[low...high] 做暂存器。每一次比较元素 A[s] 和 A[t],将小的元素添加到辅助数组 B,如果相同就把 A[s] 添加进去。

然后更新索引,如果 A[s] ≤ A[t],则 s 加 1,否则 t 加 1,当条件 s=middle+1 或 t=high+1 成立时过程结束。

s=middle+1 时,我们把数组 A[t...high] 中剩余的元素添加到 B,

t=high+1 时,把数组 A[s...middle] 中剩余的元素添加到 B。

最后,把数组 B[low...high] 复制回 A[low...high]。

 

过程  Merge

输入  数组 A[1...n] 和它的三个索引 low, middle, high, 1 ≤ low ≤ middle < high ≤ n,

          两个子数组 A[low...middle] 和 A[middle+1...high] 各自按升序排列

输出  合并两个子数组 A[low...middle] 和 A[middle+1...high] 的数组 A[low...high]

 

算法描述

comment: B[low...high] 是个辅助数组

s ← low; t ← middle+1; index ← low

while s ≤ middle and t ≤ high

    if A[s] ≤ A[t] then

        B[k] ← A[s]

        s ← s + 1

    else

        B[k] ← A[t]

        t ← t + 1

    end if

    index ← index + 1

end while

if s = middle+1 then B[k...high] ← A[t...high]

else B[k...high] ← A[s...middle]

end if

A[low...high] ← B[low...high]

 

以下是此算法的 Java 实现:

private static void merge(int[] array, int low, int middle, int high)
{
	int length = high - low + 1;
	
	int indexLowToMiddle = low;			// 从 low 位置开始的索引		
	int indexMiddleToHigh = middle + 1;	// 从 middle+1 位置开始的索引

	int[] tempArray = new int[length];
	int tempIndex = 0;

	while (indexLowToMiddle <= middle && indexMiddleToHigh <= high)
	{
		if (array[indexLowToMiddle] <= array[indexMiddleToHigh])
		{
			tempArray[tempIndex] = array[indexLowToMiddle];
			indexLowToMiddle += 1;
		}
		else
		{
			tempArray[tempIndex] = array[indexMiddleToHigh];
			indexMiddleToHigh += 1;
		}

		tempIndex += 1;
	}

	if (indexLowToMiddle == middle + 1)
	{
		System.arraycopy(
			array, indexMiddleToHigh, tempArray, tempIndex, length - tempIndex);
	}
	else
	{
		System.arraycopy(
			array, indexLowToMiddle, tempArray, tempIndex, length - tempIndex);
	}

	System.arraycopy(tempArray, 0, array, low, length);
}
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值