归并排序(代码注释超详细)
归并排序:
(复制粘贴百度百科没什么意思),简单来说,就是对数组进行分组,然后分组进行排序,排序完最后再整合起来排序!
我看了很多博客,都是写的8个数据呀什么的(2^4,分组方便),我就想着,要是10个数据呢,他们那种就没怎么讲清楚,下面我来讲一下我所理解的归并排序!
思路整理如下所示:
下面用代码来实现(代码注释超详细):
用来判断整合几次的最外层循环!
void MergeSort(int *arr, int len) //这块用了函数调用 当然你给上面那玩意写到这个里面完全可以
{for(int i=1; i<len; i*=2)//首先来看假如数组有八位满足不满足条件 (2^3)<8不成立 也就是四四合并之后 就完成了合并 查看上面图 满足条件//再来看假如有10个值 (2^4)<10不成立 也就是八八合并之后 需要四次合并 查看上图 满足条件{Merge(arr, len, i); //调用函数主体 直接写到这个循环中也完全ok}
}
函数主体:
//8 6 3 2 7 1 9 5 4 0
//如上所示 单个数的时候 L1 = H1就是这个数字本身
//68 23 17 59 04
//这块拿前两个分好的数组为例 arr[L1] = 6 arr[H1] = 8 arr[L2] = 2 arr[H2] = 3
//2368 1579 04
//拿这组举例的话 arr[L1] = 2 arr[H1] = 8 arr[L2] = 1 arr[H2] = 9
//12356789 04
//arr[L1] = 1 arr[H1] = 9 arr[L2] = 0 arr[H2] = 4
void Merge(int* arr, int len, int gap)
{//数组本身空间不够,这块早堆区申请一个和数组等长的动态内存int* brr = (int*)malloc(sizeof(int) * len);assert(brr != NULL);//int L1 = 0; //这块就到归并排序的精髓了 假设第一步,gap的值是1 一一合并L1 = 0 H1 = 0int H1 = L1 + gap - 1; //接上行 合并之后L1 = 0,H1 = 1int L2 = H1 + 1; //到这儿之后 按照上图来说68 23 arr[L1] = 6 arr[H1] = 8;int H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;//那么arr[L2] = 2 arr[H2] = 3 ; L2 = H1 + 1 = 2 ; //H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1 = 3;这里写个三目运算符主要是用来判断L2+gap如果越界len的话,那么H2的下标值为len-1int i = 0;// 堆区申请来的空间brr存放数据的下标while (L2 < len) //这块为什么要L2 < len 呢 先想一下 如果用L1 H1的话 跑到后期 L2早就越界了导致左边的白跑{ //然后使用L2的时候可以保证右边的数组最少取到一个值 使用H2的话会导致提前越界 导致有些数据不能成功排序while (L1 < H1 && L2 < H2){if (arr[L1] <= arr[L2]){brr[i++] = arr[L1++]; //这块后置++的原因是先用再加 难以理解的话可以写成下面这种/*brr[i] = arr[L1];i++, L1++;*/}else{brr[i++] = arr[L2++];}}while (L1 <= H1)//因为上面的内层while中是 "&&" 可能其中一项满足 但是另外一项不满足 因此退出了while循环 因此写这么一句 { //如果左边还有数据 挪下来brr[i++] = arr[L1++];}while (L2 <= H2)//如果右边组还有数据,挪下来{brr[i++] = arr[L2++];}L1 = H2 + 1; //因为数据得遍历完分组排序 这是在新的分好的数组中的左值与右值 与上面一毛一样H1 = L1 + gap - 1;L2 = H1 + 1;H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;}//这块退出while就是右边的arr中数组L2越界了(while(L2<len)) 此时右边肯定没有数据了//至于arr中左边的数组还有没有值 不确定再来个判断while (L1 < len){brr[i++] = arr[L1++];}//然后再将brr中数组导入到arr中即可 for (int i = 0; i < len; i++){arr[i] = brr[i];}free(brr); //堆区空间的释放
}
将代码写一块就是:
//8 6 3 2 7 1 9 5 4 0
//如上所示 单个数的时候 L1 = H1就是这个数字本身
//68 23 17 59 04
//这块拿前两个分好的数组为例 arr[L1] = 6 arr[H1] = 8 arr[L2] = 2 arr[H2] = 3
//2368 1579 04
//拿这组举例的话 arr[L1] = 2 arr[H1] = 8 arr[L2] = 1 arr[H2] = 9
//12356789 04
//arr[L1] = 1 arr[H1] = 9 arr[L2] = 0 arr[H2] = 4
void Merge(int* arr, int len, int gap)
{//数组本身空间不够,这块早堆区申请一个和数组等长的动态内存int* brr = (int*)malloc(sizeof(int) * len);assert(brr != NULL);//int L1 = 0; //这块就到归并排序的精髓了 假设第一步,gap的值是1 一一合并L1 = 0 H1 = 0int H1 = L1 + gap - 1; //接上行 合并之后L1 = 0,H1 = 1int L2 = H1 + 1; //到这儿之后 按照上图来说68 23 arr[L1] = 6 arr[H1] = 8;int H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;//那么arr[L2] = 2 arr[H2] = 3 ; L2 = H1 + 1 = 2 ; //H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1 = 3;这里写个三目运算符主要是用来判断L2+gap如果越界len的话,那么H2的下标值为len-1int i = 0;// 堆区申请来的空间brr存放数据的下标while (L2 < len) //这块为什么要L2 < len 呢 先想一下 如果用L1 H1的话 跑到后期 L2早就越界了导致左边的白跑{ //然后使用L2的时候可以保证右边的数组最少取到一个值 使用H2的话会导致提前越界 导致有些数据不能成功排序while (L1 < H1 && L2 < H2){if (arr[L1] <= arr[L2]){brr[i++] = arr[L1++]; //这块后置++的原因是先用再加 难以理解的话可以写成下面这种/*brr[i] = arr[L1];i++, L1++;*/}else{brr[i++] = arr[L2++];}}while (L1 <= H1)//因为上面的内层while中是 "&&" 可能其中一项满足 但是另外一项不满足 因此退出了while循环 因此写这么一句 { //如果左边还有数据 挪下来brr[i++] = arr[L1++];}while (L2 <= H2)//如果右边组还有数据,挪下来{brr[i++] = arr[L2++];}L1 = H2 + 1; //因为数据得遍历完分组排序 这是在新的分好的数组中的左值与右值 与上面一毛一样H1 = L1 + gap - 1;L2 = H1 + 1;H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;}//这块退出while就是右边的arr中数组L2越界了(while(L2<len)) 此时右边肯定没有数据了//至于arr中左边的数组还有没有值 不确定再来个判断while (L1 < len){brr[i++] = arr[L1++];}//然后再将brr中数组导入到arr中即可 for (int i = 0; i < len; i++){arr[i] = brr[i];}free(brr); //堆区空间的释放
}void MergeSort(int *arr, int len) //这块用了函数调用 当然你给上面那玩意写到这个里面完全可以
{for(int i=1; i<len; i*=2)//首先来看假如数组有八位满足不满足条件 (2^3)<8不成立 也就是四四合并之后 就完成了合并 查看上面图 满足条件//再来看假如有10个值 (2^4)<10不成立 也就是八八合并之后 需要四次合并 查看上图 满足条件{Merge(arr, len, i); //调用函数主体 直接写到这个循环中也完全ok}
}
主要就是H2的取值怎么取值和思路是重点那块是重点!
“但凡辛苦,皆是礼物”
归并排序(代码注释超详细)相关推荐
- TCP协议的服务器与客户端的程序设计(代码注释超详细)
在上篇博客中讲到了三次握手和四次挥手: Linux网络编程--TCP中的三次握手和四次挥手_神厨小福贵!的博客-CSDN博客服务器编程和客户端编程的大致流程如下:三次握手是在客户端中的connect中 ...
- Java菜鸟笔记:Java猜字母游戏完整代码 注释超详细(三次机会,计算总分,可运行)
import java.util.Scanner; import java.util.regex.Pattern; /*** 猜字母游戏,程序随机生成一个五个长度不重复的字母数组,要求用户也输入五个字 ...
- 学习pandas全套代码【超详细】数据查看、输入输出、选取、集成、清洗、转换、重塑、数学和统计方法、排序
大家早上好,本人姓吴,如果觉得文章写得还行的话也可以叫我吴老师.欢迎大家跟我一起走进数据分析的世界,一起学习! 感兴趣的朋友可以关注我的数据分析专栏,里面有许多优质的文章跟大家分享哦. 本篇博客将会给 ...
- 400 多行代码!超详细 Rasa 中文聊天机器人开发指南 | 原力计划
作者 | 无名之辈FTER 责编 | 夕颜 出品 | 程序人生(ID:coder_life) 本文翻译自Rasa官方文档,并融合了自己的理解和项目实战,同时对文档中涉及到的技术点进行了一定程度的扩展, ...
- Github上传代码菜鸟超详细教程
最近需要将课设代码上传到Github上,之前只是用来fork别人的代码. 这篇文章写得是windows下的使用方法. 第一步:创建Github新账户 第二步:新建仓库 第三部:填写名称,简介(可选), ...
- 用Kotlin语言开发玩安卓,基于基于Material Design+AndroidX + MVP + RxJava + Retrofit等优秀的开源框架开发,注释超详细,方便大家练手
WanAndroid 一位练习时长两年半的安卓练习生根据鸿神提供的WanAndroid开放Api来制作的产品级App,基本实现了所有的功能,使用Kotlin语言,基于Material Design+A ...
- win10环境下下载安装openpose(only cpu)并在pycharm中运行代码(超详细)
win10环境下下载安装openpose(only cpu)并在pycharm中运行代码(超详细) (一)前言 (二)准备工作 (三)友情提醒 (四)详细安装步骤 1.新建文件夹 2.下载OpenPo ...
- Deep Learning:基于pytorch搭建神经网络的花朵种类识别项目(内涵完整文件和代码)—超详细完整实战教程
基于pytorch的深度学习花朵种类识别项目完整教程(内涵完整文件和代码) 相关链接:: 超详细--CNN卷积神经网络教程(零基础到实战) 大白话pytorch基本知识点及语法+项目实战 文章目录 基 ...
- Git(2)-- Git安装后首次配置与第一次使用Git和Github管理自己的代码(超详细纯小白图文教程)
文章目录 0.写在前面: 一.注册Github 1.注册Github: 2.登录 3.创建仓库 二.安装Git 三.配置Git和Github(Git安装好后首次使用需要配置完成后才可以使用) 1.打开 ...
最新文章
- Flink从Kafka 0.8中读取多个Topic时的问题
- 家校通Android源码,基于Android的家校通系统设计与实现
- 带有无参数的存储过程
- Change FZU - 2277(线段树+dfs序)
- element ui表单校验prop的链式写法----源码分析
- ajax jsonp img
- php curl 返回cookie_分享新浪图床上传接口PHP源码
- 浅谈公路工程项目管理的发展趋势
- 【FPGA基础】DDR的基本原理介绍,DDR快速上手使用
- 安装Win10 Ubuntu20.04双系统
- 使用 Eclipse TPTP 测试 Web 应用的方法与扩展
- 路飞项目整体流程(二)
- 面试官问“为什么应聘这个岗位”,应该如何回答?
- 任意用户注册任意用户密码修改
- java8-ZoneId
- 用原生js实现淘宝详情页图片放大镜效果
- MATLAB 信号与系统
- CVE-2010-2729(MS10-061)
- Bolt介绍及基于其的实例
- 阿里云前端专家冯军:前端用户体验该如何优化