目录
1.归并排序
1.1二路归并操作的功能
归并排序与上述基于交换、选择等排序的思想不一样,归并的含义是将两个或两个以上的有序表合并成一个新的有序表。
假定待排序表含有n个记录,则可将其视为n个有序的子表,每个子表的长度为1,然后两两归并,得到个长度为 2 或 1 的有序表;
继续两两归并……如此重复,直到合并成一个长度为n的有序表为止,这种排序算法称为二路归并排序。
图8.9所示为二路归并排序的一个例子,经过三趟归并后合并成了有序序列。
1.2算法思想
Merge()的功能是将前后相邻的两个有序表归并为一个有序表。
设两段有序表 A[low..mid]、A[mid+1..high]存放在同一顺序表中的相邻位置,先将它们复制到辅助数组 B中。
每次从B的两段中取出一个记录进行关键字 的比较,将较小者放入中,当B中有一段的下标超出其对应的表长(即该段的所有元素都已复制到中)时,将另一段的剩余部分直接复制到A中。
1.3代码分析
算法如下:
ElemType *B=(ElemType *)malloc((n+1)*sizeof(ElemType));//辅助数组 B
void Merge(ElemType A[],int low,int mid,int high){
//表A的两段A[low..mid]和a[mid+1..high]各自有序,将它们合并成一个有序表
int i,j,k;
for(k=low;k<=high;k++)
B[k]=A[k]; //将A中所有元素复制到B中
for(i=low,j=mid+1,k=i;i<=mid && j<=hiqh;k++){
if(B[i]<=B[j]) //比较B的两个段中的元素
A[k]=B[i++]; //将较小值复制到A中
else
A[k]=B[j++];
}
while(i<=mid) A[k++]=B[i++]; //若第一个表未检测完,复制
while(j<=high) A[k++]=B[j++]; //若第二个表未检测完,复制
}
注意:在上面的代码中,最后两个 while 循环只有一个会执行。
一趟归并排序的操作是,调用次算法 merge(),将 L[1..n]中前后相邻且长度为h的有序段进行两两归并,得到前后相邻、长度为2h的有序段,整个归并排序需要进行
趟。
递归形式的二路归并排序算法是基于分治的,其过程如下。
- 分解:将含有n个元素的待排序表分成各含n/2个元素的子表,采用二路归并排序算法对两个子表递归地进行排序。
- 合并:合并两个已排序的子表得到排序结果。
void MergeSort(ElemType A[],int low,int high){
if(low<high){
int mid=(low+high)/2; //从中间划分两个子序列
MergeSort(A,low,mid); //对左侧子序