超详细解析C++实现归并排序算法

目录
  • 一、前言
    • 分治算法
    • 分治算法解题方法
  • 二、归并排序
    • 1.问题分析
    • 2.算法设计
    • 3.算法分析
  • 三、AC代码

一、前言

分治算法

归并排序,其实就是一种分治算法 ,那么在了解归并排序之前,我们先来看看什么是分治算法。在算法设计中,我们引入分而治之的策略,称为分治算法,其本质就是将一个大规模的问题分解为若干个规模较小的相同子问题,分而治之。

分治算法解题方法

1.分解:

将要解决的问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题。

2.治理:

求解各个子问题。由于各个子问题与原问题形式相同,只是规模较小而已,而当子问题划分得足够小时,就可以用简单的方法解决。

3.合并

按原问题的要求,将子问题的解逐层合并构成原问题的解。

二、归并排序

1.问题分析

归并排序是比较稳定的排序方法。它的基本思想是把待排序的元素分解成两个规模大致相等的子序列。如果不易分解,将得到的子序列继续分解,直到子序列中包含的元素个数为1。因为单个元素的序列本身就是有序的,此时便可以进行合并,从而得到一个完整的有序序列。

2.算法设计

(1)分解:

将待排序的元素分成大小大致一样的两个子序列。

(2)治理:

对两个子序列进行个并排序。

(3)合并:

将排好序的有序子序列进行合并,得到最终的有序序列。

3.算法分析

首先我们先给定一个无序的数列(42,15,20,6,8,38,50,12),我们进行合并排序数列,如下图流程图所示:

步骤一:首先将待排序的元素分成大小大致相同的两个序列。

步骤二:再把子序列分成大小大致相同的两个子序列。

步骤三:如此下去,直到分解成一个元素停止,这时含有一个元素的子序列都是有序的。

步骤四:进行合并操作,将两个有序的子序列合并为一个有序序列,如此下去,直到所有的元素都合并为一个有序序列。

举例,下面我将以序列(4,9,15,24,30,2,6,18,20)进行图解。

(1)初始化:i = low,j = mid+1,mid = (low+hight)/2 ,申请一个辅助数组 b

int* b = new int[hight - low + 1];  //用 new 申请一个辅助函数
	int i = low, j = mid + 1, k = 0;    // k为 b 数组的小标

(2)现在比较 a [i]  和 b[j]  ,将较小的元素放在 b 数组中,相应的指针向后移动,直到 i > mid 或者 j>hight 时结束。

while (i <= mid && j <= hight)
 {
	if (a[i] <= a[j])
	{
		b[k++] = a[i++];  //按从小到大存放在 b 数组里面
	}
	else
	{
		b[k++] = a[j++];
	}
  }

进行第一次比较 a[i]=4  和 a[j]=2,将较小的元素 2 放入数组  b  中,j++,k++,如下图:

进行第二次比较 a[i]=4  和 a[j]=6,将较小的元素放 4 入数组  b  中,i++,k++,如下图:

进行第三次比较 a[i]=9  和 a[j]=6,将较小的元素放 6 入数组  b  中,j++,k++,如下图:

进行第四次比较 a[i]=9  和 a[j]=18,将较小的元素放 9 入数组  b  中,i++,k++,如下图:

进行第五次比较 a[i]=15  和 a[j]=18,将较小的元素放 15 入数组  b  中,i++,k++,如下图:

进行第六次比较 a[i]=24  和 a[j]=18,将较小的元素放 18 入数组  b  中,j++,k++,如下图:

进行第七次比较 a[i]=24  和 a[j]=20,将较小的元素放 20 入数组  b  中,j++,k++,如下图:

此时,j>hight 了,while循环结束,但 a 数组还剩下元素(i<mid)可直接放入  b  数组就可以了。如下图所示:

while (i <= mid)  // j 序列结束,将剩余的 i 序列补充在 b 数组中
	{
		b[k++] = a[i++];
	}
	while (j <= hight)// i 序列结束,将剩余的 j 序列补充在 b 数组中
	{
		b[k++] = a[j++];
	}

现在将  b  数组的元素赋值给 a 数组,再将 b  数组销毁,即可。

for (int i = low; i <= hight; i++)  //将 b 数组的值传递给数组 a
	{
		a[i] = b[k++];
	}
	delete[]b;     // 辅助数组用完后,将其的空间进行释放(销毁)

(3)递归的形式进行归并排序

void mergesort(int* a, int low, int hight) //归并排序
{
	if (low < hight)
	{
		int mid = (low + hight) / 2;
		mergesort(a, low, mid);          //对 a[low,mid]进行排序
		mergesort(a, mid + 1, hight);    //对 a[mid+1,hight]进行排序
		merge(a, low, mid, hight);       //进行合并操作
	}
}

三、AC代码

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
void merge(int* a, int low, int mid, int hight)  //合并函数
{
	int* b = new int[hight - low + 1];  //用 new 申请一个辅助函数
	int i = low, j = mid + 1, k = 0;    // k为 b 数组的小标
	while (i <= mid && j <= hight)
	{
		if (a[i] <= a[j])
		{
			b[k++] = a[i++];  //按从小到大存放在 b 数组里面
		}
		else
		{
			b[k++] = a[j++];
		}
	}
	while (i <= mid)  // j 序列结束,将剩余的 i 序列补充在 b 数组中
	{
		b[k++] = a[i++];
	}
	while (j <= hight)// i 序列结束,将剩余的 j 序列补充在 b 数组中
	{
		b[k++] = a[j++];
	}
	k = 0;  //从小标为 0 开始传送
	for (int i = low; i <= hight; i++)  //将 b 数组的值传递给数组 a
	{
		a[i] = b[k++];
	}
	delete[]b;     // 辅助数组用完后,将其的空间进行释放(销毁)
}
void mergesort(int* a, int low, int hight) //归并排序
{
	if (low < hight)
	{
		int mid = (low + hight) / 2;
		mergesort(a, low, mid);          //对 a[low,mid]进行排序
		mergesort(a, mid + 1, hight);    //对 a[mid+1,hight]进行排序
		merge(a, low, mid, hight);       //进行合并操作
	}
}
int main()
{
	int n, a[100];
	cout << "请输入数列中的元素个数 n 为:" << endl;
	cin >> n;
	cout << "请依次输入数列中的元素:" << endl;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	mergesort(a, 0, n-1);
	cout << "归并排序结果" << endl;
	for (int i = 0; i < n; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	return 0;
}

以上就是超详细解析C++实现归并排序算法的详细内容,更多关于C++归并排序算法的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++归并排序算法详解

    目录 一.算法简介 二.实现过程 总结 一.算法简介 归并排序算法的平均时间复杂度是O(nlogn),归并算法的实现就是通过分冶法,将一个待排序列分成一个个小的序列,然后对这些小的序列进行排序,然后进行合并,合并的时候也会进行排序,这样,从整体拆成小块,再从小块合成整体的一个过程. 二.实现过程 1)拆分待排序列 2)进行排序合并 给大家写了一个简单的过程以便大家理解. 这基本就是归并排序的实现原理了,那么代码是怎么实现的呢,下面给大家展示下代码实现. //时间复杂度是nlogn #includ

  • c++归并排序详解

    说一说归并排序 归并排序:归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,效率为O(n log n).1945年由约翰·冯·诺伊曼首次提出.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行. 归并排序的核心思想是将两个有序的数列合并成一个大的有序的序列.通过递归,层层合并,即为归并. 如图,从下到上,每一步都需要将两个已经有序的子数组合并成一个大的有序数组,如下是实现合并的具体代码,请

  • C++实现的归并排序算法详解

    本文实例讲述了C++实现的归并排序算法.分享给大家供大家参考,具体如下: 归并排序 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法. 该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列: 即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 归并过程 1.比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到temp[k]中,并令i

  • C++实现归并排序(MergeSort)

    本文实例为大家分享了C++实现归并排序的具体代码,供大家参考,具体内容如下 一.思路:稳定排序 (1)划分:一直调用划分过程,直到子序列为空或只有一个元素为止,共需log2(n): (2)归并:将两个子序列从小到大合并为一个序列 二.实现程序: // 归并排序:(二路归并) // (1)递归分解数组: // (2)合并有序的序列 #include <iostream> using namespace std; // 合并两个有序的序列 template <typename T> v

  • C++实现归并排序算法

    归并 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 算法描述 归并操作的工作原理如下: 1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 2.设定两个指针,最初位置分别为两个已经排序序列的起始位置 3.比较两个指针所指向的元素,选择相对小

  • C++归并排序算法实例

    归并排序 归并排序算法是采用分治法的一个非常典型的应用.归并排序的思想是将一个数组中的数都分成单个的:对于单独的一个数,它肯定是有序的,然后,我们将这些有序的单个数在合并起来,组成一个有序的数列.这就是归并排序的思想.它的时间复杂度为O(N*logN). 代码实现 复制代码 代码如下: #include <iostream> using namespace std;   //将有二个有序数列a[first...mid]和a[mid...last]合并. void mergearray(int

  • 超详细解析C++实现归并排序算法

    目录 一.前言 分治算法 分治算法解题方法 二.归并排序 1.问题分析 2.算法设计 3.算法分析 三.AC代码 一.前言 分治算法 归并排序,其实就是一种分治算法 ,那么在了解归并排序之前,我们先来看看什么是分治算法.在算法设计中,我们引入分而治之的策略,称为分治算法,其本质就是将一个大规模的问题分解为若干个规模较小的相同子问题,分而治之. 分治算法解题方法 1.分解: 将要解决的问题分解为若干个规模较小.相互独立.与原问题形式相同的子问题. 2.治理: 求解各个子问题.由于各个子问题与原问题

  • 超详细解析C++实现快速排序算法的方法

    目录 一.前言 1.分治算法 2.分治算法解题方法 二.快速排序 1.问题分析 2.算法设计 3.算法分析 三.AC代码 一.前言 1.分治算法 快速排序,其实是一种分治算法,那么在了解快速排序之前,我们先来看看什么是分治算法.在算法设计中,我们引入分而治之的策略,称为分治算法,其本质就是将一个大规模的问题分解为若干个规模较小的相同子问题,分而治之. 2.分治算法解题方法 1.分解: 将要解决的问题分解为若干个规模较小.相互独立.与原问题形式相同的子问题. 2.治理: 求解各个子问题.由于各个子

  • Go语言单元测试超详细解析

    目录 一.单元测试分类及其概念 1.基本分类 2.细说单元测试分类 二.结合代码细说每一种测试 1.基准测试 2.组测试与子测试 三.pprof调试工具 1.对主函数进行传参 2.pprof性能调优 前言: 平时根据需求写代码.人工进行测试往往不会面面俱到,还会因为需求的改变繁琐的进行测试通过完成一个测试函数,可以大大简化测试的步骤,并且在需求该变的时候只需要改变一下测试的输入与期望 一.单元测试分类及其概念 1.基本分类 测试函数 函数前缀为Test 主要用于测试程序的一些逻辑行为是否正确 基

  • Java 超详细讲解十大排序算法面试无忧

    目录 排序算法的稳定性: 一.选择排序 二.冒泡排序 三.插入排序 四.希尔排序 五.堆排序 六.归并排序 七.快速排序 八.鸽巢排序 九.计数排序 十.基数排序 排序算法的稳定性: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,如果排序以后,保证这些记录的相对次序保持不变,即在原序列中,a[i]=a[j],且 a[i] 在 a[j] 之前,排序后保证 a[i] 仍在 a[j] 之前,则称这种排序算法是稳定的:否则称为不稳定的. 一.选择排序 每次从待排序的元素中选择最小的元素,依次

  • C++带头双向循环链表超详细解析

    目录 什么是带头双向循环链表 带头双向循环链表常用接口实现 上期我们讲完了无头单向非循环链表,这期我们接着来讲链表中结构最复杂的带头双向循环链表! 本期主要内容: 什么是带头双向循环链表? 带头双向循环链表常用接口实现! 顺序表和链表的区别和联系! 什么是带头双向循环链表 什么是带头?双向?循环?(带头双向循环链表) 带头:代表链表存在一个哨兵位节点,也就是头节点,这个节点不存放任何的有效数据! 双向:每个节点都有两个指针,分别指向它的前一个节点和后一个节点! 循环:最后一个节点next不再指向

  • C++ 二叉树的实现超详细解析

    目录 1.树的概念及结构(了解) 1.1树的概念: 1.2树的表示法: 2.二叉树的概念及结构 2.1二叉树的概念: 2.2特殊的二叉树: 2.3二叉树的性质: 2.4二叉树的顺序存储: 2.5二叉树的链式存储: 3.二叉树链式结构的实现 3.1二叉树的前中后序遍历: 3.2求二叉树的节点个数: 3.3求二叉树的叶子节点个数: 3.4销毁二叉树: 1.树的概念及结构(了解) 1.1树的概念: 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合.把它叫做树是因为它看

  • C++ 栈和队列的实现超详细解析

    目录 1.栈的介绍: 2.栈的常用接口实现 3.队列的介绍 4.队列的常用接口实现 可算是把链表给结束了,很多小伙伴已经迫不及待想看到栈和队列了,那么它来了!相信有了顺序表和链表的基础,栈和队列对于你们来讲也是轻轻松松,那我就废话不多说,直接进入今天的重点: 1.栈的介绍: 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则. 压栈:栈的插入操作叫做

  • C语言超详细梳理排序算法的使用

    目录 排序的概念及其运用 排序的概念 排序运用 插入排序 直接插入排序 希尔排序 选择排序 直接选择排序 堆排序 交换排序之冒泡排序 总结 排序的概念及其运用 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作. 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次 序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排 序算法

  • 详解vue3.0 diff算法的使用(超详细)

    前言:随之vue3.0beta版本的发布,vue3.0正式版本相信不久就会与我们相遇.尤玉溪在直播中也说了vue3.0的新特性typescript强烈支持,proxy响应式原理,重新虚拟dom,优化diff算法性能提升等等.小编在这里仔细研究了vue3.0beta版本diff算法的源码,并希望把其中的细节和奥妙和大家一起分享. 首先我们来思考一些大中厂面试中,很容易问到的问题: 1 什么时候用到diff算法,diff算法作用域在哪里? 2 diff算法是怎么运作的,到底有什么作用? 3 在v-f

  • Python超详细分步解析随机漫步

    创建RandomWalk类 为模拟随机漫步,我们将创建一个RandomWalk类,随机选择前进方向,这个类有三个属性,一个存储随机漫步的次数,另外两个存储随机漫步的每个点的x,y坐标,每次漫步都从点(0,0)出发 from random import choice class RandomWalk(): '''一个生成随机漫步数据的类''' def __init__(self,num_points=5000): '''初始化随机漫步的属性''' self.num_points = num_poi

随机推荐