在学算法设计课中,学到合并排序时,并把合并排序的三种不同的写法都写了一遍(两种递归的形式其实大同小异,只是在一种写法中整个算法只分配了一个临时数组而一种写法中每次递归时都会分配临时空间用于暂存数据)。
一、递归形式的一种写法(每次递归操作中都分配新的空间)
void merge1(item * A, item * B, item * C, int Lb, int Lc){
int i = 0, j = 0, k = 0;
while(i < Lb && j < Lc){
if(B[i] <= C[j] )
A[k++] = B[i++];
else
A[k++] = C[j++];
}
if(i < Lb)
while(i < Lb)
A[k++] = B[i++];
else
while(j < Lc)
A[k++] = C[j++];
}
/* A为待排序数组 n为数组长度 */
void merge_sort1(item * A, int n){
if(n > 1){
int m = n/2;
item * B = new int[m + 1];//将数组A元素复制到数组B与C
item * C = new int[m + 1];
int i;
for(i = 0; i < m; i++)
B[i] = A[i];
for(i = 0; i < n - m; i++)
C[i] = A[i + m];
merge_sort1(B, m);//递归调用
merge_sort1(C, n - m);
merge1(A, B, C, m , n - m);//合并两个有序数组
}
}
void merge1(item * A, item * B, item * C, int Lb, int Lc){
int i = 0, j = 0, k = 0;
while(i < Lb && j < Lc){
if(B[i] <= C[j] )
A[k++] = B[i++];
else
A[k++] = C[j++];
}
if(i < Lb)
while(i < Lb)
A[k++] = B[i++];
else
while(j < Lc)
A[k++] = C[j++];
}
/* A为待排序数组 n为数组长度 */
void merge_sort1(item * A, int n){
if(n > 1){
int m = n/2;
item * B = new int[m + 1];//将数组A元素复制到数组B与C
item * C = new int[m + 1];
int i;
for(i = 0; i < m; i++)
B[i] = A[i];
for(i = 0; i < n - m; i++)
C[i] = A[i + m];
merge_sort1(B, m);//递归调用
merge_sort1(C, n - m);
merge1(A, B, C, m , n - m);//合并两个有序数组
}
}
二、递归形式的第二种写法(整个算法只new了一个临时数组,后面操作都共用)
typedef int item;
void merge2(item * p, item * q, int first, int mid, int last){
int f = first, j = mid + 1, k = 0;
while(f <= mid && j <= last){
if(p[f] < p[j]){
q[k ++] = p[f ++];
}
else{
q[k ++] = p[j ++];
}
}
if(f <= mid){
while(f <= mid)
q[k ++] = p[f ++];
}else
while(j <= last)
q[k ++] = p[j ++];
int i;
for(i = 0; i < k; i++)//将已排序数组复制到原数组
p[first + i] = q[i];
}
/* p为待排序数组, q为临时数组 */
void merge_sort2(item *p, item *q, int n1, int n2){
if(n1 < n2){
int m = (n1 + n2)/2;
merge_sort2(p, q, n1, m);
merge_sort2(p, q, m + 1, n2);
merge2(p, q, n1, m, n2);
}
}
三、非递归形式
原来的递归过程是将待排序集合一分为二,直至排序集合就剩下一个元素位置,然后不断的合并两个排好序的数组。而非递归思想为,将数组中的相邻元素两两配对,并将其排序,构成n/2组长度为2的排序好的子数组段,然后再将他们排序成长度为4的子数组段,如此继续下去,直至整个数组排好序。
typedef int item;
void merge3(item * p, int first, int mid, int last){
if(mid > last)//重要的判断
return;
int f = first, j = mid + 1, k = 0;
item *q = new item[last - first + 1];//用于暂时存放的数组
while(f <= mid && j <= last){
if(p[f] < p[j]){
q[k ++] = p[f ++];
}
else{
q[k ++] = p[j ++];
}
}
if(f <= mid){
while(f <= mid)
q[k ++] = p[f ++];
}else
while(j <= last)
q[k ++] = p[j ++];
int i;
for(i = 0; i < k; i++)//将已排序数组复制到原数组
p[first + i] = q[i];
}
/* p为待排序数组 n为数组长度 */
void merge_sort3(item * p, int n){
int i, m = 2;
while(m <= n){
i = 0;//!
while(i + m <= n){
merge3(p, i, i + m/2 - 1, i + m -1);
i += m;
}
merge3(p, i, i + m/2 - 1, n -1);//尾部残余处理
m *= 2;
}
merge3(p, 0, m/2 - 1, n - 1);//最后一次对两个有序数组做合并排序
}