nwpu-2020级算法实验1-problemB

Overview

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

有两种实现方式:

  • 自上而下的递归

    • 所有的递归都可以由迭代重写。

  • 自下而上的迭代

算法步骤

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

  4. 重复步骤 3 直到某一指针达到序列尾;

  5. 将另一序列剩下的所有元素直接复制到合并序列尾。

其实就是leetcode中我做过的暴力合并数组

链接:4. 寻找两个正序数组的中位数 - 力扣(LeetCode) (leetcode-cn.com)

直观演示

算法分析

动图展示了我们实现算法的过程,而这个分治图静态展示了递归的流程。

:递归拆分子序列,递归深度易得logn

:将有序子序列合并为更大的有序序列。

下面是治的最后一步的过程(熟练可略过):

算法实现

C递归

 1 //归并排序递归
2 #include<stdio.h>
3 //#include<stdlib.h>
4 //#include<iostream>
5 using namespace std;
6 void merge_sort_recursive(int arr[], int reg[], int start, int end) {
7 if (start >= end)
8 return;
9 //停止递归的条件,即只有单个元素时必定有序
10 int len = end - start, mid = (len >> 1) + start;
11 int start1 = start, end1 = mid;//第一个数组
12 int start2 = mid + 1, end2 = end;//第二个数组
13 merge_sort_recursive(arr, reg, start1, end1);
14 merge_sort_recursive(arr, reg, start2, end2);
15 //将数组拆分,直到上面的if生效(即每个子序列只有单个元素),此时停止递归,开始回溯
16 int k = start;
17 while (start1 <= end1 && start2 <= end2)
18 reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
19 //这种写法更为简洁,实现的就是谁小谁放进去
20 while (start1 <= end1)
21 reg[k++] = arr[start1++];
22 while (start2 <= end2)
23 reg[k++] = arr[start2++];
24 //多余元素直接放入reg
25 for (k = start; k <= end; k++)
26 arr[k] = reg[k];
27 //一次返回赋值,即把reg里排好序的元素粘回arr
28 }
29 ​
30 void merge_sort(int arr[], const int len) {
31 int reg[len];//构造算法步骤中所说的新的数组
32 merge_sort_recursive(arr, reg, 0, len - 1);
33 //启动递归
34 //输出
35 for(int i = 0; i < len; i++){
36 printf("%d\n", arr[i]);
37 }
38 //此处还可以clear *reg来保证代码安全。
39 }
40 int main(){
41 int n;
42 scanf("%d", &n);
43 int Array[n];
44 for(int i = 0; i < n; i++){
45 scanf("%d", &Array[i]);
46 }
47 merge_sort(Array, n);
48 return 0;
49 }

参考文章:

1.5 归并排序 | 菜鸟教程 (runoob.com)

算法学习->归并排序的更多相关文章

  1. Java常见排序算法之归并排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  2. 啃算法:归并排序及JavaScript实现

    在学习归并排序之前,有必要了解分治法,因为归并排序正是应用了分治模式.(基本定义摘自<算法导论>) 一.分治法 1.思想: 将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些 ...

  3. DSP算法学习-过采样技术

    DSP算法学习-过采样技术 彭会锋 2015-04-27 23:23:47 参考论文: 1 http://wr.lib.tsinghua.edu.cn/sites/default/files/1207 ...

  4. 算法学习之C语言基础

    算法学习,先熟悉一下C语言哈!!! #include <conio.h> #include<stdio.h> int main(){ printf(+); getch(); ; ...

  5. Python之路,Day21 - 常用算法学习

    Python之路,Day21 - 常用算法学习   本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...

  6. C / C++算法学习笔记(8)-SHELL排序

    原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...

  7. 算法学习之BFS、DFS入门

    算法学习之BFS.DFS入门 0x1 问题描述 迷宫的最短路径 给定一个大小为N*M的迷宫.迷宫由通道和墙壁组成,每一步可以向相邻的上下左右四格的通道移动.请求出从起点到终点所需的最小步数.如果不能到 ...

  8. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

  9. Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...

随机推荐

  1. Seata–分布式事务

    10.1 分布式事务基础 10.1.1 事务 事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作都成功,要么所有的操作都被撤销.简单地说,事务提供一种"要 ...

  2. UWP - 介绍App Service 与新功能

    App Service 是一种背景工作运行的服务,提供给其他Apps 使用就像Web Service.它本身无使用介面(UI-less),允许Apps 在同一个设备被引用,甚至Windows 10 1 ...

  3. Redis 在项目中合理使用经验总结

    转自:https://my.oschina.net/u/920698/blog/3031587 背景 Redis 是一个开源的内存数据结构存储系统. 可以作为数据库.缓存和消息中间件使用. 支持多种类 ...

  4. div 居中显示

    <html lang="en"> <head> <meta charset="UTF-8"> <title>di ...

  5. Sentinel限流、降级配置详解

    安装Sentinel 下载sentinel-dashboard-1.8.2.jar 安装有jdk环境,8080端口未被占用 在jar包所在目录打开cmd,输入命令启动:java -jar sentin ...

  6. Nginx+Tomcat+Memcached实现session共享

    实验环境: server1:nginx tomcat memcached server2:tomcat memcached Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入 ...

  7. golang map实现原理

    这篇文章主要讲 map 的赋值.删除.查询.扩容的具体执行过程,仍然是从底层的角度展开.结合源码,看完本文一定会彻底明白 map 底层原理. 我要说明的是,这里对 map 的基本用法涉及比较少,我相信 ...

  8. grpc基础

    RPC 框架原理 RPC 框架的目标就是让远程服务调用更加简单.透明,RPC 框架负责屏蔽底层的传输方式(TCP 或者 UDP).序列化方式(XML/Json/ 二进制)和通信细节.服务调用者可以像调 ...

  9. android kotlin 子线程中调用界面UI组件崩溃

    UI 只能在主线程内更新,子线程需要更新UI组件时可以这样: fun fuck(){ Executors.newSingleThreadExecutor().execute{ // url reque ...

  10. mybaits源码分析--事务管理(八)

    一.事务管理 写到这也快进入收尾阶段了了,在介绍MyBatis中的事务管理时不可避免的要接触到DataSource的内容,所以接下来会分别来介绍DataSource和Transaction两块内容. ...