归并排序非递归实现(C语言)

  • 任务描述:实现非递归的合并排序算法

  • 算法介绍:归并排序是将一个序列先分成最小数量的子集(此时每一个子集含有一个元素,属于一种递增序列),然后将相邻的两个子集进行合并成一个新的递增子集序列,重复下去,直到将序列中所有元素实现递增排序。

  • 参考文献:《算法设计与分析》(第三版)郑宗汉 郑晓明著。

  • 详细代码如下:

#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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值