一 递归 :
/** 递归版本
* 采用分治的方法,将n个元素自顶向下分成两个n/2的子问题, 再将子问题进行划分,
* 最终将整个问题分解成每个字表长度为 1 的有序表,然后自底向上成对归并。
**/
#include <stdio.h>
int b[100]; //中间过程数组
void merge(int a[], int low, int mid, int high){
// 此时a[] 的a[low,mid] 和a[mid+1,high]各自都是有序的,属于成对的两个子问题
//需要合并成一个有序表
int i, j, k;
i = low;
j = mid + 1;
k = 0;
for (k=0; i <= mid&&j <= high; k++){
//将较小的先放入b[]
if (a[i] < a[j])
b[k] = a[i++];
else
b[k] = a[j++];
}
while (i <= mid) b[k++] = a[i++];
while (j <= high) b[k++] = a[j++];
// 将已有序的数据b[0,k-1]拷贝到a[low,high]中
for (i = low,j=0; i <= high; i++,j++){
a[i] = b[j];
}
}
void mergeSort(int a[], int low, int high){
if (low < high){//划分
int mid = (low + high) / 2;
mergeSort(a, low, mid); //左子问题
mergeSort(a, mid + 1, high);//右子问题
merge(a, low, mid, high);//归并两个子问题
}
}
int main(){
int a[8] = {
1, 6, 3, 2, 9, 8, 7, 5
};
//8个元素
int n = 8;
mergeSort(a, 0, n - 1);
for (int i = 0; i < n; i++){
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
二 非递归:
整个思想如下图,和递归方法思想是一致的。
/** 非递归版本
* 同样对数据进行划分,每一趟从左到右,从上到下,依次归并
* merge()函数和递归版本一样。主要区别在于mergeSort()里的每次步长的计算和归并。
**/
#include <stdio.h>
int b[100]; //中间过程数组
void merge(int a[], int low, int mid, int high){
// 此时a[] 的a[low,mid] 和a[mid+1,high]各自都是有序的,属于成对的两个子问题
//需要合并成一个有序表
int i, j, k;
i = low;
j = mid + 1;
k = 0;
for (k=0; i <= mid&&j <= high; k++){
//将较小的先放入b[]
if (a[i] < a[j])
b[k] = a[i++];
else
b[k] = a[j++];
}
while (i <= mid) b[k++] = a[i++];
while (j <= high) b[k++] = a[j++];
// 将已有序的数据b[0,k-1]拷贝到a[low,high]中
for (i = low,j=0; i <= high; i++,j++){
a[i] = b[j];
}
}
void mergeSort(int a[],int n){
int step = 1;//步长 分别是1,2,4,8...
while (step <= n){
int low = 0;
while (low + step <= n){
int mid = low + step - 1;
int high = mid + step;
if (high > n){
high = n; //数据个数不是2的整数次方,最后的数据可能不足step个。
}
merge(a,low, mid, high);
low = high + 1; //按照上图 ,从左到右
}
step *= 2; //按照上图 ,从上到下
}
}
int main(){
int a[8] = {
1, 6, 3, 2, 9, 8, 7,5
};
//8个元素
int n = 8;
mergeSort(a,n - 1);
for (int i = 0; i < n; i++){
printf("%d ", a[i]);
}
printf("\n");
return 0;
}