急死我了机试之MergeSort

LeetCode原题链接

0.忘差不多的基础知识

return用法

1.正文

排序问题,想试试分而治之的归并排序,这是一个涉及到递归的算法,使用时需考虑以下几点问题:

  1. how to devide --func merge
  2. how to merge while sort --func merge_sort
  3. what we need:
    (1)index:p q mid
    (2)array:numList arrayLeft arryRight

1.0 overroll

将 [p,q] 分为[p,mid] 和 [mid+1,q] 区域,Left和Right两部分分别分割成单一数组元素后再进行排序与合并。

 merge_sort_L(arr, p, mid);
 merge_sort_R(arr, mid + 1, q);

便于区分与理解所以加了L&R,实际两个都是merge_sort函数,以实现递归操作。

详细实现过程在1.1与1.2中叙述。

1.1 merge_sort

递归中止原则:

  1. numList ==NULL
  2. p>=q

算法难点为理解实现分、并递归代码的执行顺序,这边摘取merge_sort部分代码展示:

merge_sort(arr, p, mid);
merge_sort(arr, mid + 1, q);
//对分好的 [p,mid] 和 [mid,q] 进行归并操作
merge(arr, p, mid, q);

对照下图,进行步骤顺序的分析
Left:
S1 merge_sort_L(1,8)
S2 merge_sort_L(1,4)
S3 merge_sort_L(1,2)
S4 merge_sort_L(1,1)

p == q ,故return回到merge_sort_L(1,2)下一句

S5 merge_sort_R(2,2)

p == q ,故return回到merge_sort_R(2,2)下一句

S6 merge(1,2)

到这里结束了下图中7,5的分割、排序、归并。

剩余的步骤自行debug查看,不再赘述,下面放分而治之的流程图以供理解。
在这里插入图片描述

1.2 merge

needed:

  1. tmp数组
  2. L_low L_high R_low R_high

实现:
S1:compare与copy,排序结果先进tmp数组。

if(arrayL>arrayR){
tmp=arrayL
}

期间有L_low、R_low分别指向左右数组当前比较单元,故二者存在++操作,且数值应<=L_hogh\R_high。

//1.compare与copy,L R 比较完后移,排序结果先进tmp数组

for (i = 0; L_low <= L_high && R_low <= R_high; i++) {
    if (numList[L_low] < numList[R_low]) {
        tmp[i] = numList[L_low];
        L_low++;
    } else {
        tmp[i] = numList[R_low];
        R_low++;
    }

S2:左数组剩余,直接copy。

剩余条件判断为L_low <= L_high。
将剩余元素copy进tmp数组应该从S1的最后一个下标后。

S3:右数组剩余,直接copy。

同S2

S4:copy。
应该注意递归算法,所以numList不是每次都从[0]开始copy,而是从[first]开始。

在这里插入图片描述
在这里插入图片描述

2.完整代码

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

#define Nmax 100

void merge(int numList[], int first, int mid, int last) {

    int i, j;

    //每次需要排序的divided数组大小都不一样
    //进行动态分配临时数组
    int* tmp = (int*)malloc((last - first + 1) * sizeof(int));

    int L_low = first;
    int L_high = mid;
    int R_low = mid + 1;
    int R_high = last;

    //1.compare与copy,L R 比较完后移,排序结果先进tmp数组

    for (i = 0; L_low <= L_high && R_low <= R_high; i++) {
        if (numList[L_low] < numList[R_low]) {
            tmp[i] = numList[L_low];
            L_low++;
        } else {
            tmp[i] = numList[R_low];
            R_low++;
        }
    }

    //2.L left
    if (L_low <= L_high) {
        for (j = L_low; j <= L_high; j++) {
            tmp[i] = numList[j];
            i++;
        }
    }
    //3.R left
    if (R_low <= R_high) {
        for (j = R_low; j <= R_high; j++) {
            tmp[i] = numList[j];
            i++;
        }
    }


    //4.copy 回numList\
    //注意递归,所以first+i
    for (i = 0; i < last - first + 1; i++) {
        numList[first + i] = tmp[i];
    }
    
    
    free(tmp);//


}

void merge_sort(int numList[], int first, int last) {

    int mid;

    if (first < last) {
        mid = (first + last) / 2;
        //对Left进行递归分割
        merge_sort(numList, first, mid);
        //对Right进行递归分割
        merge_sort(numList, mid + 1, last);
        merge(numList, first, mid, last);

    }


}





int main() {
    int N, i;
    int numList[Nmax];

    //1.input
    scanf("%d", &N);
    for (i = 0; i < N; i++) {
        scanf("%d", &numList[i]);

    }
    //2.func
    merge_sort(numList, 0, N - 1);


    //3.output
    for (i = 0; i < N; i++) {
        printf("%d ", numList[i]);
    }



}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周树皮不皮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值