归并排序的想法其实是比较简单的,但是实现起来却并没有那么容易。现在我们思考如可将两个局部有序的两个数组组合成一个有序的序列,我们有An,Bn两个序列且局部有序,首先我们要新开辟一个新的数组空间Cn。然后我们从An,Bn两个序列中依次选取合适的元素加入Cn,我们要用两个变量来标记An,Bn的下标,伪代码如下:
for (…)
{
if(A[i] > B[j])
{
C[k] = A[i];
i++;
}
else
{
C[k] = B[j];
j++;
}
if (A有剩余)
{将A剩余的元素加入C};
else
{将B剩余的元素加入C};
}
我们思考这个的时候是不是可以想象到归并算法的思想了呢,就是将有序的多个归并成一个,可能会有同学问,可是我们只有一个呀,这就是算法的另一个要点:分裂,我们要利用递归先局部有序,然后实现整体有序。
算法实现图解:
我们接下来看一下代码:
归并排序:
void Merge (Sqlist L,Sqlist &L1,int left,int right,int mid) //注意这里的引用加在了目的数组的后面;
{
int i,j,k;
for (i = left,j = mid + 1,k = left;i <= mid && j<= right;k++)
{
if (L.elem[i].data < L.elem[j].data)
L1.elem[k] = L.elem[i++];
else if (L.elem[i].data >= L.elem[j].data)
L1.elem[k] = L.elem[j++];
} //注意这里的虽然i或j不满足条件了,但是k++会执行最后一次!!!!!
if (i <= mid)
while (i <= mid)
L1.elem[k++] = L.elem[i++];
if (j <= right)
while (j <= right)
L1.elem[k++] = L.elem[j++];
}
void Msort(Sqlist L,Sqlist <,int left,int right) //同样注意这里的引用位置!!
{
int mid;
Sqlist L2;
L2.elem = new Elementype[N];//开辟新的数组空间;
if (left == right)
LT.elem[left] = L.elem[left];
else
{
mid = (left + right) / 2; //找到分裂点
Msort(L,L2,left,mid); //分裂点左侧进行归并排序
Msort(L,L2,mid + 1,right);//分裂点右侧进行归并排序
Merge(L2,LT,left,right,mid)//将以排序的两组进行归并
}
}
void Merge_sort(Sqlist &L)
{
Msort(L,L,1,L.length);
}
算法在用的过程中从新生成了一个数组,所以数据转移的路径大概如下:
L------>L2-------->L;
归并算法在考研中不要求代码级别,但是我们还要以掌握代码为目标!!!