任务描述:实现非递归的合并排序算法
算法介绍:归并排序是将一个序列先分成最小数量的子集(此时每一个子集含有一个元素,属于一种递增序列),然后将相邻的两个子集进行合并成一个新的递增子集序列,重复下去,直到将序列中所有元素实现递增排序。
参考文献:《算法设计与分析》(第三版)郑宗汉 郑晓明著。
详细代码如下:
#include<stdio.h>
#include<stdlib.h>
void merge(int A[], int p, int q, int r) {
int left1 = p;
int right1 = q;
int left2 = q + 1;
int right2 = r;
//已知[left1,right1]为递增区间,[left2,right2]为递增区间,将其合并为一个递增序列
int len = r - p + 1;
int k = 0;//用来指明数组下标
int* bp = (int*)malloc((len) * sizeof(int));//申请一个空间,存储合并后的序列
if (bp) {//保证在bp分配空间成功的情况下执行以下代码
//遍历两个子序列
while (left1 <= right1 && left2 <= right2) {
if (A[left1] <= A[left2])
bp[k++] = A[left1++];
else
bp[k++] = A[left2++];
}
//如果左序列遍历完毕,将右序列未遍历完的元素直接加到bp中
while (left1 > right1) {
if (left2 > right2)
break;
bp[k++] = A[left2++];
}
//如果右序列遍历完毕,将左序列未遍历完的元素直接加到bp中
while (left2 > right2) {
if (left1 > right1)
break;
bp[k++] = A[left1++];
}
//将结果复制到A数组中
k = 0;
for (int i = p; i <= r; i++)
A[i] = bp[k++];
}
free(bp);//释放空间
}
void merge_sort(int A[], int n) {
int gap = 1;//此时子集序列所含有的元素个数
while (gap < n) {
for (int i = 0; i < n; i += 2 * gap) {
int p = i, q = i + gap - 1, r = i + 2 * gap - 1;
int left2 = q + 1;
//合并时只有左序列,右序列不存在,此时不需要合并
if (left2 >= n)
break;
//合并时右序列只有部分数据,需要修正右边界
if (r >= n)
r = n - 1;
merge(A, p, q, r);
}
gap *= 2;
}
}
int main() {
int A[] = { 7,3,1,8,6,4,5,2 };
int len = sizeof(A) / sizeof(A[0]);
int i;
merge_sort(A, len);
for (i = 0; i < len; i++) {//打印输出
printf("%d\t", A[i]);
}
printf("\n");
return 0;
}
小结:
课后写这个代码写了好久,书上的源代码抄上去运行结果显示错误,就看别的大佬写的代码自己好好理解了一下,然后结合书上代码重新码了一遍,总算成功了。
另外,这个合并排序算法的时间复杂度为O(nlogn),空间复杂度为O(n)。