归并排序-(C语言实现)

#include <stdio.h>
#include <stdlib.h>

/**整体思想:分治 + 递归*/

// 归并两个已经有序的数组,L、M和R分别是左边界、分界点和右边界
// 这里将右边数组的第一个元素的下标作为了分界点
void merge(int array[], int L, int M, int R) {
    // 求出左右两部分数组的大小
    int LEFT_SIZE = M - L;
    int RIGHT_SIZE = R - M + 1;
    // 分别定义左右两个数组存放原数组中左右两边的数据
    int left[LEFT_SIZE];
    int right[RIGHT_SIZE];
    int i, j, k;

    // 填上左边的数组
    for (i = L; i < M; i++) {
        left[i - L] = array[i];
    }
    // 填上右边的数组
    for (i = M; i <= R; i++) {
        right[i - M] = array[i];
    }

    // 初始化三个变量为对应数组的起始位置
    // i: 指向left数组的起始位置
    // j: 指向right数组的起始位置
    // k: 指向array数组的起始位置
    i = 0;
    j = 0;
    k = L;

    // 比较left和right数组中i和j指向的元素的大小进行归并,将元素填充到array数组中
    while (i < LEFT_SIZE && j < RIGHT_SIZE) {
        if (left[i] < right[j]) {
            array[k] = left[i];
            i++;
            k++;
        } else {
            array[k] = right[j];
            j++;
            k++;
        }
    }
    // 将left或者right数组中剩余的元素填充到array数组中
    while (i < LEFT_SIZE) {
        array[k] = left[i];
        i++;
        k++;
    }
    while (j < RIGHT_SIZE) {
        array[k] = right[j];
        j++;
        k++;
    }
}

// 实现分治,将数组不断二分的过程
void merge_sort(int array[], int L, int R) {
    // 如果这一段只有一个元素,那么它一定是有序的
    if (L == R) {
        return ;
    } else { // 否则将数组二分
        int M = (L + R) / 2;
        merge_sort(array, L, M);
        merge_sort(array, M + 1, R);
        // 这里需要注意,我们这里求出来的M和上面merge函数中传过去的M
        // 表示的位置实际上是不一样的,这里求出来的M刚好指向了左半边
        // 数组的最后一个元素,而merge函数中需要的M指向的是右半边数组
        // 的第一个元素,所以这里把M加1当作参数传给merge函数进行调用
        merge(array, L, M + 1, R);
    }
}

int main()
{
    // 定义测试数组
    int array[] = {7, 3, 4, 9, 2, 1, 0, 13};
    int L = 0;
    int R = 7;
    // 调用归并函数进行排序
    merge_sort(array, L, R);

    // 遍历展示
    int i;
    for (i = 0; i <= R; i++) {
        printf("%d\n", array[i]);
    }
    return 0;
}

运行结果:
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值