首页 > 编程语言 >[排序算法] 归并排序 (C++)

[排序算法] 归并排序 (C++)

时间:2022-11-20 14:58:52浏览次数:40  
标签:归并 递归 int C++ 序列 排序 left

归并排序解释

归并排序 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);
}


程序运行结果图

标签:归并,递归,int,C++,序列,排序,left
From: https://www.cnblogs.com/MAKISE004/p/16908457.html

相关文章

  • windows--cmake与c++的使用教程(13)
    1概述本文基于前文环境本节目标:为发布项目关闭调试控制台(/SUBSYSTEM:WINDOWS)2CMake脚本设置debug显示控制台还是很有帮助的,可输出调试信息到控制台,观察成勋运......
  • windows--cmake与c++的使用教程(12)
    1概述本文基于前文环境本节目标:为项目增加链接选项:requireAdministrator(/level='requireAdministrator'),用于增加管理员权限2目标程序安装C盘(windows默认系......
  • windows--cmake与c++的使用教程(11)
    1概述本文基于前文环境本节目标:设置项目包含头文件路径,关键语法target_include_directories。2目标main.cc与Typedef.h不在同一个目录下,Typedef.h位于incl......
  • c++中参数传递的三种方式
    一、值传递通过值传递传递的形参实际上是对实参的一个拷贝,对形参进行修改操作,不会影响到实参的值。【实例】#include<iostream>usingnamespacestd;voidchange(i......
  • Effective C++ - 条款27 - 尽量少做转型动作
    旧式C转型:T(expression)/(T)expression新式C++转型:static_cast/dynamic_cast/const_cast/reinterpret_cast只能通过const_cast去掉constdynamic_cast成本很高,很多编......
  • c++报错:[Error] 'cout' was not declared in this scope
    一、报错代码#include<iostream>intmain(){intx=10;cout<<x<<"\n";return0;} 二、解决方法在代码中加入:usingnamespacestd;正确代......
  • 排序 草稿
    //这里将map.entrySet()转换成list,再用collections工具类中的sort()方法完成排序操作List<Map.Entry<String,Long>>list=newArrayList<>(collect.entrySet())......
  • C++实例会员管理程序
    设计快捷店会员的简单管理程序。基本要求如下:(1)定义人民币RMB类,实现人民币的基本运算和显示。(2)定义会员member类,表示会员的基本信息,包括:编号(按建立会员的顺序自动生成),姓名,密......
  • C++ 类的项目练习 定义一个类,来表示某模拟养成游戏中人物: 每个人物, 有昵称,年龄,性别,
    Hero.h:#pragmaonce#include<iostream>#include<string>#include<vector>#include<sstream>usingnamespacestd;typedefenumgender{Man,//男W......
  • C++机票购买系统
    C++机票购买系统机票购买系统该系统有两类用户,会员(多名)和管理员(1名)。其中,会员功能包括:1、首先注册并录入个人信息,包括:用户名,密码,生日,邮箱。注册后,自动设置会员编号。2......