02归并排序——分治递归

02_归并排序_——分治_递归_

#include <stdio.h>void merge(int arr[], int l, int m, int r)
{int n1 = m -l + 1;int n2 = r -m;//创建临时数组int L[n1], R[n2];for(int i = 0; i < n1; i++){L[i] = arr[l + i];}for(int j = 0; j < n2; j++){R[j] = arr[m + 1 + j];}int i = 0, j = 0, k = l;while(i < n1 && j < n2){if(L[i] <= R[j]){arr[k] = L[i];i++;}else{arr[k] = R[j];j++;}k++;}while(i < n1){arr[k] = L[i];i++;k++;}while(j < n2){arr[k] = R[j];j++;k++;}
}void mergeSort(int arr[], int l, int r)
{if(l < r){int m = l + (r - 1) / 2;mergeSort(arr, l, m);mergeSort(arr, m + 1, r);mergeSort(arr, l, m, r);}
}void printArrary(int arr[], int size)
{for(i = 0; i < sieze; i++){printf("%d ", arr[i]);}printf("\n");
}int main()
{int arr[] ={12, 11, 10, 5, 6, 3};int arr_sieze = sizeof(arr) / siezeof(arr[0]);printf("排序前的数组:\n");printArray(arr, arr_size);mergeSort(arr, 0, arr_size - 1);printf("排序后的数组:\n");printArray(arr, arr_size);return 0;
}

notion

递归

递归指的是一个函数直接或间接调用自身。递归通常用于解决可以分解为子问题的复杂问题,每个子问题的结构与原问题相似

  1. 基准情况:

    这是递归函数的终止条件,当满足这个条件时,递归停止,直接返回结果

  2. 递归情况:

    这是递归函数调用自身的地方,将问题分解成一个或多个子问题,然后递归地解决这些子问题

从栈的角度分析递归
第一次调用:

入栈

  1. mergeSort(arr, 0, 5) 被调用
  2. l = 0, r = 5, 计算中间点 m = 2
  3. 入栈 mergeSort(arr, 0, 2) 和mergeSort(arr, 3, 5)

出栈

  1. 等待 mergeSort(arr, 0, 2)mergeSort(arr, 3, 5) 完成

  2. 合并 merge(arr, 0, 2, 5)

第二次调用(左半部分)

入栈

  • mergeSort(arr, 0, 2) 被调用。
  • l = 0, r = 2, 计算中间点 m = 1
  • 入栈 mergeSort(arr, 0, 1)mergeSort(arr, 2, 2)

出栈

  • 等待 mergeSort(arr, 0, 1)mergeSort(arr, 2, 2) 完成。
  • 合并 merge(arr, 0, 1, 2)
第三次调用(左半部分的左半部分)

入栈

  • mergeSort(arr, 0, 1) 被调用。
  • l = 0, r = 1, 计算中间点 m = 0
  • 入栈 mergeSort(arr, 0, 0)mergeSort(arr, 1, 1)

出栈

  • 等待 mergeSort(arr, 0, 0)mergeSort(arr, 1, 1) 完成。
  • 合并 merge(arr, 0, 0, 1)
基准情况

入栈

  • mergeSort(arr, 0, 0) 被调用。
  • l = 0, r = 0,满足基准情况,直接返回。
  • 入栈 mergeSort(arr, 1, 1) 被调用。
  • l = 1, r = 1,满足基准情况,直接返回。

出栈

  • mergeSort(arr, 0, 0)mergeSort(arr, 1, 1) 返回后,合并 merge(arr, 0, 0, 1)
  • mergeSort(arr, 0, 1) 返回。

从栈的角度分析,不断的入栈,规模不断减小,等待基准条件满足再回归(出栈),最高回归出结果

分治

过将一个复杂问题分解为较小的子问题,逐个解决这些子问题,然后合并解决方案来解决原问题。归并排序是分治法的典型例子。分治法的主要步骤包括:

  1. 分解(Divide):将原问题分解成若干个规模较小但形式与原问题相同的子问题
  2. 解决(Conquer):递归地解决这些子问题。当子问题规模足够小时(达到基准情况),直接解决
  3. 合并(Combine):将子问题的解决方案合并成原问题的解决方案
归并中的分治
分解

在归并排序中,数组arr[1…r] 被分解成两个数组:

左半部分:arr[l…m]

右半部分:arr[m+1…r]

其中,m 是中间点,计算公式为:m = l + (r - l) / 2

解决

对于每个子数组,递归地调用 mergeSort,继续将其分解成更小的子数组,直到每个子数组只包含一个元素或为空(达到基准情况),这时不需要进一步分解,直接返回

合并

当递归返回时,子数组已经有序,然后调用merge函数,将两个有序的子数组合并成一个有序的数组

归并排序的分治过程eg

假设我们有一个数组 arr = {12, 11, 13, 5, 6, 7},我们调用 mergeSort(arr, 0, 5)

  1. 初始数组arr = {12, 11, 13, 5, 6, 7}
  2. 第一次分解
    • 左半部分:{12, 11, 13}
    • 右半部分:{5, 6, 7}
  3. 继续分解左半部分
    • {12, 11, 13} -> {12, 11}{13}
    • {12, 11} -> {12}{11}
  4. 基准情况
    • {12}{11} 不再分解,直接返回。
  5. 合并左半部分
    • 合并 {12}{11} -> {11, 12}
    • 合并 {11, 12}{13} -> {11, 12, 13}
  6. 继续分解右半部分
    • {5, 6, 7} -> {5, 6}{7}
    • {5, 6} -> {5}{6}
  7. 基准情况
    • {5}{6} 不再分解,直接返回。
  8. 合并右半部分
    • 合并 {5}{6} -> {5, 6}
    • 合并 {5, 6}{7} -> {5, 6, 7}
  9. 最终合并
    • 合并 {11, 12, 13}{5, 6, 7} -> {5, 6, 7, 11, 12, 13}

最终,数组被排序为 {5, 6, 7, 11, 12, 13}

{6}不再分解,直接返回。 8. **合并右半部分**: - 合并{5}{6}->{5, 6} - 合并{5, 6}{7}->{5, 6, 7}9. **最终合并**: - 合并{11, 12, 13}{5, 6, 7}->{5, 6, 7, 11, 12, 13}`

最终,数组被排序为 {5, 6, 7, 11, 12, 13}

在这里插入图片描述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/864986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mp4格式怎么转换成mp3格式,简鹿格式工厂轻松转换

mp4格式怎么转换成mp3格式&#xff1f;MP3主要关注音频内容的压缩与传播&#xff0c;而MP4则是一个更为复杂的多媒体容器&#xff0c;能够包含视频、音频等多种媒体流&#xff0c;适合于现代多样化的媒体消费场景。 而有一些视频中的音频可能深受用户喜爱&#xff0c;可是如何…

分布式锁的详细解析

分布式锁工具 一、背景 当前问题&#xff1a;项目中会使用到分布式锁用于定时任务、接口幂等性处理&#xff0c;但是分布式锁的实现较简单&#xff0c;会出现执行超时、加解锁失败等场景。分布式锁都有哪些实现&#xff0c;他们的优劣势是什么呢&#xff1f; 二、现有技术 分…

【第13章】MyBatis-Plus流式查询

文章目录 前言一、常用方法二、使用示例总结 前言 MyBatis-Plus 从 3.5.4 版本开始支持流式查询&#xff0c;这是 MyBatis 的原生功能&#xff0c;通过 ResultHandler 接口实现结果集的流式查询。这种查询方式适用于数据跑批或处理大数据的业务场景。 在 BaseMapper 中&#…

【信息系统项目管理师知识点速记】组织通用管理:知识管理

23.3 知识管理 23.3.1 知识管理基础 知识管理是通过利用各种知识和技术手段,帮助组织和个人生产、分享、应用和创新知识,以形成知识优势并在个人、组织、业务目标、经济绩效和社会效益方面产生价值的过程。它能为组织带来知识增值,创造新的价值,提升决策效能和水平,是提…

《昇思 25 天学习打卡营第 8 天 | 模型保存与加载使用静态图加速 》

活动地址&#xff1a;https://xihe.mindspore.cn/events/mindspore-training-camp 签名&#xff1a;Sam9029 保存与加载模型没有多少内容&#xff0c;就把使用静态图加速一起看了 先说说现有理解的概念 在学习深度学习的过程中&#xff0c;经常需要保存训练好的模型参数&#…

snowflake 不再是个数据仓库公司了

标题先上结论&#xff0c;为啥这么认为&#xff0c;且听接下来道来。 snowflake 非常成功&#xff0c;开创了云数仓先河&#xff0c;至今在数仓架构上也是相对比较先进的&#xff0c;国内一堆模仿的公司&#xff0c;传统上我们会认为 snowflake 肯定是一家数据仓库公司。不过最…

网络攻防题录集

文章目录 第一章 网络攻防概述第二章 密码学第三章 网络协议脆弱性分析第四 自测题三第五章 自测题五第六章 自测题六第七章 自测题七第八章 自测题八第九章 自测题九第十章 自测题十第十一章 自测题十一第十二章 自测题十二第十三章 自测题十三 第一章 网络攻防概述 第一代安…

【Android面试八股文】App对内存是如何限制的?应该如何合理使用内存?

文章目录 一、内存管理概览二、垃圾回收三、共享内存四、分配与回收应用内存五、限制应用内存六、切换应用七、进程间的内存分配八、内存类型九、物理内存 虚拟内存9.1 物理内存9.2 虚拟内存9.3 虚拟内存的好处9.4 共享库内存十、VSS RSS PSS USS区别十一、Android系统的页面置…

JavaSEJava8 时间日期API + 使用心得

文章目录 1. LocalDate2. LocalTime3. LocalDateTime3.1创建 LocalDateTime3.2 LocalDateTime获取方法 4. LocalDateTime转换方法4.1 LocalDateTime增加或者减少时间的方法4.2 LocalDateTime修改方法 5. Period6. Duration7. 格式转换7.1 时间日期转换为字符串7.2 字符串转换为…

linux的Top学习

学习文档 https://www.cnblogs.com/liulianzhen99/articles/17638178.html TOP 问题 1&#xff1a;top 输出的利用率信息是如何计算出来的&#xff0c;它精确吗&#xff1f; top 命令访问 /proc/stat 获取各项 cpu 利用率使用值内核调用 stat_open 函数来处理对 /proc/sta…

AcWing 1256:扩展二叉树

【题目来源】https://www.acwing.com/problem/content/1258/【题目描述】 由于先序、中序和后序序列中的任一个都不能唯一确定一棵二叉树&#xff0c;所以对二叉树做如下处理&#xff0c;将二叉树的空结点用 补齐&#xff0c;如图所示。 我们把这样处理后的二叉树称为原二叉树…

持续集成(Continuous Integration)

定义 持续集成&#xff08;Continuous Integration&#xff0c;简称CI&#xff09;是一种软件开发实践&#xff0c;开发者频繁地将代码集成到共享的代码库中&#xff0c;每次集成都通过自动化构建和测试来验证&#xff0c;从而尽早发现并修复错误。CI的目标是提高软件开发的质量…

[C++] 退出清理函数解读(exit、_exit、abort、atexit)

说明&#xff1a;在C中&#xff0c;exit、_exit&#xff08;或_Exit&#xff09;、abort和atexit是用于控制程序退出和清理的标准库函数。下面是对这些函数的详细解读&#xff1a; exit 函数原型&#xff1a;void exit(int status);作用&#xff1a;exit函数用于正常退出程序…

基于Java的早教系统的设计与实现【附源码】

摘要&#xff1a;随着家长对孩子教育的重视程度越来越高&#xff0c;早教也越来越受家长的青睐&#xff0c;因为它可以有针对性地单独授课&#xff0c;能显著提高学生学习的效果。同时互联网的兴起&#xff0c;对教育的形式也产生了重大影响&#xff0c;为此基于B/S的早教平台应…

零知识证明技术:隐私保护的利器

在当今信息时代&#xff0c;数据安全和隐私保护的重要性日益凸显。随着技术的发展&#xff0c;密码学在保障信息安全方面发挥着越来越重要的作用。其中&#xff0c;零知识证明技术作为一种新兴的密码学方法&#xff0c;为隐私保护提供了强有力的支持。本文将简要介绍零知识证明…

3.js - premultiplyAlpha

你瞅啥啊&#xff01;&#xff01;&#xff01; 先看效果图吧 代码 // ts-nocheck // 引入three.js import * as THREE from three // 导入轨道控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls // 导入lil.gui import { GUI } from three/ex…

c#与倍福Plc通信

bcdedit /set hypervisorlaunchtype off

pycharm中新建的临时python文件存放在哪里?

在pycharm中建立的临时python文件&#xff0c;从哪里可以找到呢&#xff1f; 1.我们打开cmd窗口&#xff0c;进入根目录&#xff0c;用dos命令“dir scratch*.py/a/s”进行查找&#xff0c;发现这些临时文件存放在Roaming\JetBrains\PyCharmCE2022.2\scratches 的目录里面 2.…

base64字符串空格问题

客户端使用的Content-Type为application/x-www-form-urlencoded时&#xff0c;字符串中出现了空格&#xff0c;base64解码时出错了&#xff0c;因为原来的字符有号&#xff0c; Spring Boot 对于Content-Type为application/x-www-form-urlencoded的HTTP请求&#xff0c;默认情…

我全都要,全网聚合神器!绝了!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 现在有不少开发者都会以“壳源”的方式&#xff08;如TVBox、阅读APP等&#xff09;&#xff0c;为用户提供了更为灵活性的选择。 而今天给大家安利的是一款“壳源”的聚合神器&#…