1,这里的归并排序指的就是2路归并排序,将一个序列不断分治,直到分成只有1个元素的序列,然后合并。
2,算法的关键在Merge。Merge是将2个有序序列合并为一个有序序列。其中分治后的最小情况,即1个元素的序列就认为是有序序列。依次逐步Merge起来。
基本思想:
void mergesort(int A[], int first, int last);
{
if(first >= last)
return;
int mid = (first+last)/2;
//分治
mergesort(A, first, mid);
mergesort(A, mid+1, last);
//合并(可以写成一个函数)
int tmp = new int[mid-first+1];
for(int i=0;i<mid-first+1;i++)
tmp[i] = A[first+i];
//i指向前半部分,j指向后半部分,k指向新数组
int i = 0, j = mid+1, k = first;
while(i<=mid-first && j<=last)
A[k++] = (A[j]<tmp[i])?A[j++]:tmp[i++];
while(i<=mid-first)
A[k++] = tmp[i++];
delete[] tmp;
}
递归形式:
void merge(int a[], int first, int mid, int last)
{
int i = first, m = mid;
int j = mid+1, n = last;
int k = 0;
int *temp = new int[last-first+1]; //借助临时空间存储归并结果
while(i<=m && j <=n)
{
if(a[i]<=a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while(i<=m)
temp[k++] = a[i++];
while(j<=n)
temp[k++] = a[j++];
for(i = 0; i<k;i++)
a[first+i] = temp[i];//归并结果放回
delete[] temp;
temp = NULL;
}
void sort(int a[], int first, int last)
{
if(first < last)
{
int mid = (first + last)/2;//分治
sort(a, first, mid);
sort(a, mid+1, last);
merge(a, first, mid, last);//合并
}
}
归并排序必须借助一个临时空间(O(n))作为辅助,上面的代码是每次Merge都临时请求合适大小的空间。也可以声明一个全局的辅助空间,每次Merge都使用同一个空间。
void merge(int a[], int first, int mid, int last, int temp[])
{
int i = first, m = mid;
int j = mid+1, n = last;
int k = 0;
while(i<=m && j <=n)
{
if(a[i]<=a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while(i<=m)
temp[k++] = a[i++];
while(j<=n)
temp[k++] = a[j++];
for(i = 0; i<k;i++)
a[first+i] = temp[i];
}
void sort(int a[], int first, int last, int temp[])
{
if(first < last)
{
int mid = (first + last)/2;
sort(a, first, mid, temp);
sort(a, mid+1, last, temp);
merge(a, first, mid, last, temp);
}
}
归并排序的非递归形式:(待续)。