归并排序是又一类不同的排序方法。归并的含义是将两个或两个以上的有序表组合成一个新的有序表。利用归并的思想容易实现排序。
算法思想:假设初始序列有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2或1的有序子序列,在两两归并,如此重复,直到得到一个长度为n的有序序列为止。这种排序方法称为2-路归并排序。
输入:顺序表的长度,顺序表中各个元素。
输出:排好序的顺序表中各个元素。
运行结果:
算法实现:
将相邻有序序列R[low..mid]和R[mid+1..high]归并为T[low..high]
void Merge(RedType R[],RedType T[],int low,int mid,int high)
{
//将相邻有序序列R[low..mid]和R[mid+1..high]归并为T[low..high]
int i=low,j=mid+1,k=low; //ijk各遍历一序列
while(i<=mid&&j<=high)
{
//选择两子序列中当前小的填入T[k]
if(R[i].key<=R[j].key)
RedCopy(T[k++],R[i++]);
else
RedCopy(T[k++],R[j++]);
}
while(i<=mid) //剩余段复制到T
RedCopy(T[k++],R[i++]);
while(j<=high)
RedCopy(T[k++],R[j++]);
for(i=low;i<=high;i++) //将合并完的T复制到R 以便下次归并时用
RedCopy(R[i],T[i]);
}
归并排序算法实现(递归):
若序列长度为1直接填入T即可,否则将原序列一分为二,左右两侧子序列递归排序,最后调用归并函数进行归并。
将R[low..high]归并排序到T[low...high] 下标不变。
void MSort(RedType R[],RedType T[],int low,int high)
{
/*归并排序
若序列为1直接填入T即可,否则,将元序列一分为二,左右两侧子
序列递归排序 最后调用归并函数进行归并 将R[low..high]归并排
序到T[low..high] 下标不变*/
int mid;
if(low==high)
RedCopy(T[low],R[low]);
else
{
mid=(low+high)/2;
MSort(R,T,low,mid); //递归排序到临时数组
MSort(R,T,mid+1,high);
Merge(R,T,low,mid,high); //归并到目标数组
}
}
归并排序.
void MergeSort(SqList &L)
{
//归并排序 递归实现
RedType *T; //临时数组
if(!(T=(RedType *)malloc((L.length+1)*sizeof(RedType))))
exit(OVERFLOW);
MSort(L.r,T,1,L.length);
free(T);
T=NULL;
}
算法分析:
时间复杂度:O(N*logN)
空间复杂度:O(N)
该算法是一种稳定的算法。
该算法还可以写成非递归的形式。
算法思想:将表中的相邻元素两两配对,用merge 对它们排序,构成n/2组长度为2的排好序的子区间段。然后将它们排序成长度为4的子区间段...如此重复啊重复,直到整个数组都排好序。
具体实现:
void Merge_Sort(SqList &L)
{
/*归并排序 非递归实现
将表中的相邻元素两两配对 用merge对他们排序 构成n/2组长度为2
的排好序的子区间段,然后将他们排序成长度为4的子区间段,如此
重复啊重复 直到整个数组排好序*/
RedType *T; //临时数组
if(!(T=(RedType *)malloc((L.length+1)*sizeof(RedType))))
exit(OVERFLOW);
int i,j,low,high,mid,pre_low,pre_high;
for(i=2;i<=L.length;i*=2) //i为子区间长,2,4,.....
{
for(j=1;j<=L.length;j+=i) //对每一小块区间进行合并
{
low=j;
high=j+i-1;
mid=(low+high)/2;
if(high>L.length) //如果high越界 合并上一个区间与这个区间
{
low=pre_low; //修改low
mid=pre_high; //修改mid
high=L.length;//修改high
}
Merge(L.r,T,low,mid,high); //合并两个区间
pre_low=low; //保存上一个区间low
pre_high=high;//保存上一个区间high
}
}
free(T);
T=NULL;
}