开源硬件
Arduino
客制化键盘
Arduino_寄存器
二进制运算
寄存器+二进制运算
LCD-逐字显示
密码依次录入
等待输入
WiFi Duck(无线击键注入攻击平台)
WiFi Duc-New
WiFi Duc-Old
蓝牙无线烧录
ESP8266
ESP-NOW
ESP8266看门狗
ESP8266-休眠模式
ESP01/01S使用说明
WIFI_SD
ESP8266-Web服务器
ESP8266-WIFI自动认证
ESP32
ESP32 ADC2
ESP32_PWM
ESP32_CAM
ESP32 小坦克
ESP32_限电保护
Arduino IDE 添加 ESP32
ESP32-iPhone BLE攻击
STM32
STM32F103-虚拟键盘
STC
STC8G1K08(A)
树莓派-触摸屏
Arduino IDE
Arduino_自制库
Arduino库收集
常见排序算法
冒泡排序
选择排序
插入排序
希尔排序
归并排序
快速排序
计数排序
预处理
millis(运行时长)
Arduino IDE 2.X-修改数据位置
Mixly
Mixly安装教程
Mixly 模块介绍
Mixly-添加ESP32CAM支持
Mixly-库定制工具
模块
4G模块连接物联网
GPS模块
语音模块(JQ8900)
安信可VB语音识别
28BYJ-48(5V步进)
FreeRTOS
FreeRTOS-多任务基础
FreeRTOS-任务共享全局变量
FreeRTOS-多核多任务
FreeRTOS-MUTEX
FreeRTOS-常规程序改多任务
FreeRTOS-定时器
LaserGRBL(激光雕刻)
LaserGRBL-GRBL
GRBL-CNC Shield v4
MicroPython
Scratch
Wokwi(在线仿真)
html转无符号数组
待做开源项目
本文档使用 MrDoc 发布
-
+
首页
归并排序
## 归并排序  归并排序是采用分治法的一个非常典型的应用。其基本思想是:将已有序的子序合并,从而得到完全有序的序列,即先使每个子序有序,再使子序列段间有序 **基本思想:** 归并排序 是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并 **算法描述:** 把长度为n的输入序列分成两个长度为n/2的子序列 2. 对这两个子序列分别采用归并排序 3. 将两个排序好的子序列合并成一个最终的排序序列 [wokwi_归并排序](https://wokwi.com/projects/332802505356345940)|[wokwi_归并排序](https://wokwi.com/projects/334327110703252050) ### 递归实现  归并排序,从其思想上看就很适合使用递归来实现,并且用递归实现也比较简单。其间我们需要申请一个与待排序列大小相同的数组用于合并过程两个有序的子序列,合并完毕后再将数据拷贝回原数组 ```c // 归并排序(主体函数),MergeSort(数组名,数组长度,[排序方向,默认小到大]) // 即每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完即可 void MergeSort(int array[], int size, boolean forward = true){ int* tmp = (int*)malloc(sizeof(int)*size); // 申请一个与原数组大小相同的空间 if (tmp == NULL) exit(-1); _MergeSort(array, 0, size - 1, tmp, forward); // 归并排序 free(tmp); // 释放空间 } // 归并排序(子函数),_MergeSort(数组名,区间开始,区间结束,数组空间,[排序方向,默认小到大]) void _MergeSort(int* a, int left, int right, int* tmp, boolean forward){ // 归并结束条件:当只有一个数据或是序列不存在时,不需要再分解 if (left >= right) return; int mid = left + (right - left) / 2; // 中间下标 _MergeSort(a, left, mid, tmp, forward); // 对左序列进行归并 _MergeSort(a, mid + 1, right, tmp, forward); // 对右序列进行归并 int begin1 = left, end1 = mid; int begin2 = mid + 1, end2 = right; // 将两段子区间进行归并,归并结果放在tmp中 int i = left; while (begin1 <= end1&&begin2 <= end2){ // 根据传入的第三个参数,来确定是正向排序(小到大)还是逆向排序(大到小) if (forward == true){ // 将较小的数据优先放入tmp if (a[begin1] < a[begin2]) tmp[i++] = a[begin1++]; else tmp[i++] = a[begin2++]; }else{ // 将较大的数据优先放入tmp if (a[begin1] > a[begin2]) tmp[i++] = a[begin1++]; else tmp[i++] = a[begin2++]; } } // 当遍历完其中一个区间,将另一个区间剩余的数据直接放到tmp的后面 while (begin1 <= end1) tmp[i++] = a[begin1++]; while (begin2 <= end2) tmp[i++] = a[begin2++]; // 归并完后,拷贝回原数组 for (int j = left; j <= right; j++) a[j] = tmp[j]; } ``` ### 非递归实现  归并排序的非递归算法并不需要借助栈来完成,我们只需要控制每次参与合并的元素个数即可,最终便能使序列变为有序 ```c // 归并排序(主体函数),MergeSortNonR(数组名,数组长度,[排序方向,默认小到大]) // 即每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完即可 void MergeSortNonR(int array[], int size, boolean forward = true){ // 申请一个与待排序列大小相同的空间,用于辅助合并序列 int* tmp = (int*)malloc(sizeof(int)*size); if (tmp == NULL) exit(-1); int gap = 1; // 需合并的子序列中元素的个数 while (gap < size){ for (int i = 0; i < size; i += 2 * gap){ int begin1 = i, end1 = i + gap - 1; int begin2 = i + gap, end2 = i + 2 * gap - 1; // 最后一组的第二个小区间不存在或是第一个小区间不够gap个,此时不需要对该小组进行合并 if (begin2 >= size) break; // 最后一组的第二个小区间不够gap个,则第二个小区间的后界变为数组的后界 if (end2 >= size) end2 = size - 1; _MergeSortNonR(array, tmp, begin1, end1, begin2, end2, forward);//合并两个有序序列 } // 下一趟需合并的子序列中元素的个数翻倍 gap = 2 * gap; } free(tmp); // 释放空间 } // 归并排序(子函数),_MergeSortNonR(数组名,数组空间,区间1开始,区间1结束,区间2开始,区间2结束,[排序方向,默认小到大]) void _MergeSortNonR(int* a, int* tmp, int begin1, int end1, int begin2, int end2, boolean forward){ int j = begin1; // 将两段子区间进行归并,归并结果放在tmp中 int i = begin1; while (begin1 <= end1&&begin2 <= end2){ // 根据传入的第三个参数,来确定是正向排序(小到大)还是逆向排序(大到小) if (forward == true){ // 将较小的数据优先放入tmp if (a[begin1] < a[begin2]) tmp[i++] = a[begin1++]; else tmp[i++] = a[begin2++]; }else{ // 将较大的数据优先放入tmp if (a[begin1] > a[begin2]) tmp[i++] = a[begin1++]; else tmp[i++] = a[begin2++]; } } // 当遍历完其中一个区间,将另一个区间剩余的数据直接放到tmp的后面 while (begin1 <= end1) tmp[i++] = a[begin1++]; while (begin2 <= end2) tmp[i++] = a[begin2++]; // 归并完后,拷贝回原数组,这里 for (j; j <= end2; j++) a[j] = tmp[j]; } ```
造物者W
2022年6月13日 13:27
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码