所谓归并(merging)是将链两个或两个以上的有序表合并成一个新的有序表。
先考虑一种特殊情形:
设线性表L[1:n]中的某段L[low:high]已经部分有序,即它的两个子表L[low:mid]与L[mid+1:high]已经有序,现要将这两个有序子表归并成一个有序子表L[low:high]。
实现上述两个子表的归并,基本做法如下:
(1) 开辟一个与线性表L同样大小的表空间A;
(2) 设置三个指针i,j,k,其初始状态分别指向两个有序子表的首部及表空间A中与L中需要进行排序段相对应空间的首部。即i=low, j=mid+1, k=0;
(3) 沿两个有序子表扫描:
若L[i]<L[j],则A[k]=L[i],且i与k的指针均加1;否则A[k]=L[j],且j与k的指针均加1。如此反复,直到有一个子表的指针已经直到末端为止(即子表内的元素已经取空)
(4) 将未取空的子表中的剩余元素依次放入表空间A中;
(5) 将A中的对应段复制到L中。
所谓归并排序,是指把一个长度为n的线性表看成由n个长度为1的有序表组成,然后反复进行两两归并,最后就得到程度为n的有序线性表。由于归并是两两进行的,因此也称为2-路归并排序。
归并排序的平均时间复杂度为O(nlogn),它是稳定的。
代码:
#include <iostream> using namespace std; void merge(double p[],int low, int mid, int high) { int i=low; int j=mid+1; int k=0; double *p1; p1=(double*)malloc((high-low+1)*sizeof(double)); while ((i<=mid)&&(j<=high)) { if (p[i]<p[j]) { p1[k]=p[i]; i++; k++; } else { p1[k]=p[j]; j++; k++; } } while (i<=mid) //将第1段余下部分复制到p1 { p1[k]=p[i]; i++; k++; } while (j<=high) //将第2段余下部分复制到p1 { p1[k]=p[j]; j++; k++; } for (k=0,i=low;i<=high;k++,i++) //将p1复制回P中 { p[i]=p1[k]; } free(p1); return; } void merge_sort(double p[], int n) { int m,k,j,low,mid,high; //double *a; //a=(double*)malloc(n*sizeof(double)); m=1; while (m<n) { k=2*m; for (j=0;j<n;j=j+k) { low=j; high=j+k-1; mid=j+m-1; if(high>n-1) high=n-1; if(high>mid) merge(p,low,mid,high); } m=k; } return; } int main() { double a[10]; int i; cout<<"输入原始序列:"<<endl; for (i=0;i<10;i++) { cin>>a[i]; } cout<<endl; merge_sort(a,10); cout<<"排序后:"<<endl; for (i=0;i<10;i++) { cout<<a[i]<<" "; } cout<<endl; return 0; }