例如有两个有序表:(7,10,13,15)和(4,8,19,20),归并后得到的有序表为:(4,7,8,10,13,15,19,20)。
归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1,如此循环下去,知道其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。
二路归并算法描述为(a[s,t]中的数据由小到大合并到r[s,t]中);
procedure merge(s,m,t);
begin
1) i:=s; j:=m+1; k:=s;
2) while (i<=m) and (j<=t) do
if a[i]<=a[j] then (r[k]:=a[i]; i:=i+1; k:=k+1)
else (r[k]:=a[j]; j:=j+1; k:=k+1);
3) while i<=m do (r[k]:=a[i]; i:=i+1; k:=k+1);
4) while j<=t do (r[k]:=a[j]; j:=j+1; k;=k+1);
end;
归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经
排序序列之和,该空间用来存放合并后的序列
第三步:比较两个
指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
归并
排序
是稳定的排序.即相等的元素的顺序不会改变.如输入记录 1(1) 3(2) 2(3) 2(4) 5(5) (括号中是记录的关键字)时输出的 1(1) 2(3) 2(4) 3(2) 5(5) 中的2 和 2 是按输入的顺序.这对要排序数据包含多个信息而要按其中的某一个信息排序,要求其它信息尽量按输入的顺序排列时很重要.这也是它比
快速排序
优势的地方.
void CopyToSrc(int *newa, int *a, int left1, int size)
{
int t = left1;
int i = 0;
while ( i < size)
{
a[t] = newa[i];
t++;
i++;
}
}
void Merge(int *a, int left1, int right1, int left2, int right2)
{
int size1 = right1 - left1 + 1;
int size2 = right2 - left2 + 1;
int size = size1 + size2;
int * newa = new int[size];
int tl1, tl2;
tl1 = left1;
tl2 = left2;
int count = 0;
while (tl1 <= right1 && tl2 <= right2)
{
if (a[tl1] <= a[tl2])
{
newa[count] = a[tl1];
tl1++;
count++;
}
else
{
newa[count] = a[tl2];
tl2++;
count++;
}
}
while(tl1 <= right1)
{
newa[count] = a[tl1];
tl1++;
count++;
}
while(tl2 <= right2)
{
newa[count] = a[tl2];
tl2++;
count++;
}
CopyToSrc(newa, a, left1, size);
delete []newa;
}
void MergeSort(int *a, int left, int right)
{
if (left < right)
{
int mid = (left + right)/2;
MergeSort(a, left, mid);
MergeSort(a, mid+1, right);
Merge(a, left, mid, mid+1, right);
}
}