[排序算法] 归并排序 (C++)
归并排序解释
归并排序 Merge Sort 是典型的分治法的应用,其算法步骤完全遵循分治模式。
分治法思想
分治法 思想: 将原问题分解为几个规模较小但又保持原问题性质的子问题,递归求解这些子问题,然后再合并这些子问题的解,最终得到原问题的解。
分治模式每层递归步骤
1、分解原问题为若干个子问题;
2、解决子问题。递归求解子问题,当子问题规模足够小时,可以直接求解;
3、合并这些子问题的解构成原问题的解。
归并排序的分治模式
1、分解未排序 n 个元素的序列成 各有 n/2 个元素的连续子序列;
2、递归排序两个连续子序列;
3、合并两个已排序的连续子序列构成整个完成排序的序列。
归并排序递归树
我们以序列 [7, 4, 8, 1, 3, 5, 6, 2] 为例构建一个归并排序的递归树
上半部分递归树为将当前长度为 n 的序列拆分成长度为 n/2 的子序列,下半部分递归树为合并已经排序的子序列。

时间复杂度
假设时间复杂度为 T(n),在递归解决当前两个规模为 n/2 的子问题时,我们需要消耗 2T(n/2)* 的时间。
在合并过程中,对于一个具有 n 个元素的序列,我们需要消耗O(n)的时间。
故时间复杂度如下

归并排序核心代码
void Merge(int a[], int left, int mid, int right){
int temp[right - left + 1]; //临时数组用于存储排序时的数
int i = left; //分成两块 i指向左边的数字 j指向右边的数字
int j = mid + 1;
int k = 0; //k用于存储数字到临时数组
while( i <= mid && j <= right ){
if(a[i] < a[j]) //永远都是 i 和 j 指向的数进行比较
temp[k++] = a[i++]; //谁小,谁就先放到临时数组中
else
temp[k++] = a[j++];
}
while( i <= mid ) //如果左边还有数没放上去,就依次放上去
temp[k++] = a[i++];
while( j <= right ) //如果是右边还有同上
temp[k++] = a[j++];
for(int m = left, n = 0; m <= right; m++, n++)//读取临时数组中的数
a[m] = temp[n];
}
void Merge_Sort(int a[], int left, int right){
if( left == right )
return;
int mid = (left + right)/2;
//递归拆分成较小规模子序列排序
Merge_Sort(a, left, mid);
Merge_Sort(a, mid + 1, right);
Merge(a, left, mid, right); //合并较小规模问题解
}
完整程序源代码
#include<iostream>
#include<ctime>
using namespace std;
void Merge(int a[], int left, int mid, int right){
int temp[right - left + 1]; //临时数组用于存储排序时的数
int i = left; //分成两块 i指向左边的数字 j指向右边的数字
int j = mid + 1;
int k = 0; //k用于存储数字到临时数组
while( i <= mid && j <= right ){
if(a[i] < a[j]) //永远都是 i 和 j 指向的数进行比较
temp[k++] = a[i++]; //谁小,谁就先放到临时数组中
else
temp[k++] = a[j++];
}
while( i <= mid ) //如果左边还有数没放上去,就依次放上去
temp[k++] = a[i++];
while( j <= right ) //如果是右边还有同上
temp[k++] = a[j++];
for(int m = left, n = 0; m <= right; m++, n++)//读取临时数组中的数
a[m] = temp[n];
}
void Merge_Sort(int a[], int left, int right){
if( left == right )
return;
int mid = (left + right)/2;
//递归拆分成较小规模子序列排序
Merge_Sort(a, left, mid);
Merge_Sort(a, mid + 1, right);
Merge(a, left, mid, right); //合并较小规模问题解
}
void Show(int a[], int n){
for(int i = 0; i < n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
main(){
int a[50];
srand((int)time(0));
for(int i = 0; i < 50; i++)
a[i] = rand() % 100 + 1;
Show(a, 50);
Merge_Sort(a, 0, 50);
cout<<endl<<endl;
Show(a, 50);
}
程序运行结果图

[排序算法] 归并排序 (C++)的更多相关文章
- 经典排序算法 - 归并排序Merge sort
经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到所有合并完,形成有序的数组 举例 无序数组[6 2 ...
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...
- 使用 js 实现十大排序算法: 归并排序
使用 js 实现十大排序算法: 归并排序 归并排序 refs js 十大排序算法 All In One https://www.cnblogs.com/xgqfrms/p/13947122.html ...
- java泛型中使用的排序算法——归并排序及分析
一.引言 我们知道,java中泛型排序使用归并排序或TimSort.归并排序以O(NlogN)最坏时间运行,下面我们分析归并排序过程及分析证明时间复杂度:也会简述为什么java选择归并排序作为泛型的排 ...
- js 实现排序算法 -- 归并排序(Merge Sort)
原文: 十大经典排序算法(动图演示) 归并排序 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得 ...
- javascript排序算法-归并排序
归并排序 概念:归并排序是一种分治算法.其思想是将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组. 时间复杂度: O(nlogn) ...
- 八大排序算法——归并排序(动图演示 思路分析 实例代码java 复杂度分析)
一.动图演示 二.思路分析 归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序 1. 向上归并排序的时候,需要一个暂存数组用来排序, 2. 将 ...
- 排序算法-归并排序(Java)
package com.rao.sort; import java.util.Arrays; /** * @author Srao * @className MergeSort * @date 201 ...
- 疯子的算法总结(六) 复杂排序算法 ① 归并排序 merge_sort()
归并排序采取了分治的思想,每次分别排左半边和右半边,不断递归调用自己,直到只有一个元素递归结束,开始回溯,调用merge函数,合并两个有序序列,再合并的时候每次给末尾追上一个最大int这样就不怕最后一 ...
- JavaScript排序算法——归并排序
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
随机推荐
- OpenHarmony3.0如何轻松连接华为云IoT设备接入平台?
摘要:本文主要介绍基于OpenHarmony 3.0版本来对接华为云IoT设备接入IoTDA,以小熊派BearPi-HM_Nano开发板为例,使用huaweicloud_iot_link SDK对接华 ...
- 使用Pipeline抽象业务生命周期流程
上篇关于流程引擎的文章还是快两年以前的<微服务业务生命周期流程管控引擎>,这中间各种低代码平台层出不穷,虽然有些仅仅是OA+表单的再度包装,但有些的确是在逻辑和操作单元层面进行了真正的高度 ...
- C语言001--hello world编译详解
1.编写hello.c程序,并编译运行 book@100ask:~/linux/c01$ cat hello.c -n 1 #include <stdio.h> 2 3 int main( ...
- kubernetes之基于ServiceAccount拉取私有镜像
前面可以通过ImagPullPolicy和ImageullSecrets指定下载镜像的策略,ServiceAccount也可以基于spec.imagePullSecret字段附带一个由下载镜像专用的S ...
- C#,使用FindWindow和FindWindowEx查找窗体和控件
函数: // Find Window // 查找窗体 // @para1: 窗体的类名 例如对话框类是"#32770" // @para2: 窗体的标题 例如打开记事本 标题是&q ...
- Java中的StringBuilder和StringBuffer适用场景
我不知道为什么这个这么老的问题会出现在我的时间线上,看了一下回答,大多是2012,2013年的回答,照说那个年代,有些历史故事还很新鲜,却不知道为什么没有一个答案说到点子上. stringbuffer ...
- ProxySQL Cluster 概述
文章转载自:https://blog.csdn.net/n88Lpo/article/details/79608639 前言 在ProxySQL 1.4.2 之前,ProxySQL 单点的解决方法有配 ...
- 使Squashfs可写的办法
yiyi@yiyi-HP-Pavilion-Notebook:~/Applications/Office2016$ pwd /home/yiyi/Applications/Office2016 yiy ...
- 关于aws-Global区的新账户的一些限制坑点
在使用global-aws的时候,遇到几个限制坑点记录如下(都是需要发请求找aws服务支持才能提高) 1.关于Elastic IPs的限制,默认为 5,这样在ec2下的Elastic IPs中最多只能 ...
- VScode开发STM32/GD32单片机-MakeFile工程JlinkRTT配置
本次使用开发板为STM32F401CCU6,使用CubeMX配置一个Makefile工程 配置时候为内部时钟 工程选择makefile工程类型 只生成需要的文件 用VSCode打开后显示很多波浪线 选 ...