归并排序是典型分治思想的代表——首先把原问题分解为两个或多个子问题,然后求解子问题的解,最后使用子问题的解来构造出原问题的解。

对于归并排序,给定一个待排序的数组,首先把该数组划分为两个子数组,然后对子数组进行排序(递归调用归并排序),最后对两个有序的子数组进行合并,使合并之后的数组为有序状态。

让我们想想,把一个数组不断地划分为子数组,不断地划分......,不断地划分......., 最后停止了划分不下去了。 此时子数组的元素有一个,它们本身就是有序的。接下来,我们就需要执行合并过程,不断地一层层向上合并,........,  直到原数组。通过这个过程就会发现, 归并排序的核心在于合并有序的子数组,而不是对子数组进行排序,因为最底层的子数组本身就是有序的,上一层子数组如果想要变成有序的,通过合并底层有序的子数组就可以得到, 最终我们使原数组变成了有序的,从而完成了排序操作。

说明几点:

1. 归并排序采用了分治思想,它的核心在于合并子问题的解而不是求解子问题(快速排序也采用了分治思想,但它的核心是在于求解子问题而不需要合并子问题的解)、

2. 归并排序不是原址排序,它有排序过程中需要借助额外的内存空间。

3. 归并排序为稳定排序(其实呢,具体还得看你怎么写代码,如果两个数的值相等时,你不保持原顺序都就会变成非稳定的了)

4. 归并排序的时间复杂度为O(NlogN).

具体代码如下:

   /***********************************************************************
* Copyright (C) 2019 Yinheyi. <chinayinheyi@163.com>
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version. * Brief:
* Author: yinheyi
* Email: chinayinheyi@163.com
* Version: 1.0
* Created Time: 2019年05月06日 星期一 22时22分57秒
* Modifed Time: 2019年05月09日 星期四 21时10分59秒
* Blog: http://www.cnblogs.com/yinheyi
* Github: https://github.com/yinheyi
*
***********************************************************************/ // 归并排序,分治法的典型代表: 将原问题分解了几个子问题,解决子问题,再合并子问题的解,
// 这样就得到了原问题的解。
// 分治本质上就是把原问题分解为几个子问题来解决。
// 快速排序也是分治思想来解决。
//
//
// 归并排序(merge-sort):
// 1. 把一个待排序的数组分解为两个子数组;
// 2. 对两个子数组进行排序(通过递归地调用自己来实现);
// 3. 对两个已经排序的数组进行合并。
//
// 分析:
// 1. 一个数组一直分解下去,只到分解成只包含一个元素的子数组为止, 此时自然是有序的;
// 2. 归并排序的重点在于合并,而不是对子数组的排序。(快速排序与它恰恰相反,快速排序的
// 重点是对子数组进行排序,而不是合并,因为它不需要合并了)
//
//
#include <cstring>
#include <iostream>
typedef bool(*CompareFunc)(int, int); // 下面函数实现合并功能,输入三个下标参数表示了两个子数组, :[nStart_, nMiddle)和[nMiddle, nEnd)
void Merge(int array[], int nStart_, int nMiddle_, int nEnd_, CompareFunc comp)
{
if (array == nullptr || nStart_ >= nMiddle_ || nMiddle_ >= nEnd_)
return; // 建立一个临时数组存放中间数据
int _nIndex = ;
int* _pTempArray = new int[nEnd_ - nStart_]; // 对两个子数组进行合并
int _nStartChange = nStart_;
int _nMiddleChange = nMiddle_;
while (_nStartChange < nMiddle_ && _nMiddleChange < nEnd_)
{
// 此处的if中比较语句的安排可以保持稳定排序的特性。
if (comp(array[_nMiddleChange], array[_nStartChange]))
{
_pTempArray[_nIndex] = array[_nMiddleChange];
++_nMiddleChange;
}
else
{
_pTempArray[_nIndex] = array[_nStartChange];
++_nStartChange;
}
++_nIndex;
} // 把不为空的子数组的元素追加到临时数
if (_nStartChange < nMiddle_)
{
memcpy(_pTempArray + _nIndex, array + _nStartChange, sizeof(int) * (nMiddle_ - _nStartChange));
}
else if (_nMiddleChange < nEnd_)
{
memcpy(_pTempArray + _nIndex, array + _nMiddleChange, sizeof(int) * (nEnd_ - _nMiddleChange));
}
else
{
/* do noting */
} // 数据交换
memcpy(array + nStart_, _pTempArray, sizeof(int) * (nEnd_ - nStart_)); delete [] _pTempArray;
_pTempArray = nullptr;
} // 归并排序功能实现函数
void MergeSort(int array[], int nStart_, int nEnd_, CompareFunc comp)
{
// 数组指针为空,或者数组内的个数少于等于1个时,直接返回。
if (nullptr == array || (nEnd_ - nStart_) <= )
return; // 划分为两个子数组并递归调用自身进行排序
int _nMiddle = (nStart_ + nEnd_) / ;
MergeSort(array, nStart_, _nMiddle, comp);
MergeSort(array, _nMiddle, nEnd_, comp); // 合并排序完成的子数组
Merge(array, nStart_, _nMiddle, nEnd_, comp);
} // 比较函数
bool less(int lhs, int rhs)
{
return lhs < rhs;
} // 打印数组函数
void PrintArray(int array[], int nLength_)
{
if (nullptr == array || nLength_ <= )
return; for (int i = ; i < nLength_; ++i)
{
std::cout << array[i] << " ";
} std::cout << std::endl;
} /*************** main.c *********************/
>>int main(int argc, char* argv[])
{
// 测试1
int array[] = {, -, , , -, -, -, , -, -};
PrintArray(array, );
MergeSort(array, , , less);
PrintArray(array, ); // 测试2
int array2[] = {};
PrintArray(array2, );
MergeSort(array2, , , less);
PrintArray(array2, ); // 测试3
int array3[] = {, -};
PrintArray(array3, );
MergeSort(array3, , , less);
PrintArray(array3, ); return ;
}

排序算法的c++实现——归并排序的更多相关文章

  1. Python排序算法(六)——归并排序(MERGE-SORT)

    有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10800699.html 一.归并排序(MERG ...

  2. 【高级排序算法】2、归并排序法的实现-Merge Sort

    简单记录 - bobo老师的玩转算法系列–玩转算法 -高级排序算法 Merge Sort 归并排序 Java实现归并排序 SortTestHelper 排序测试辅助类 package algo; im ...

  3. 【高级排序算法】1、归并排序法 - Merge Sort

    归并排序法 - Merge Sort 文章目录 归并排序法 - Merge Sort nlogn 比 n^2 快多少? 归并排序设计思想 时间.空间复杂度 归并排序图解 归并排序描述 归并排序小结 参 ...

  4. 四、排序算法总结二(归并排序)(C++版本)

    一.什么是归并排序? 归并排序是基于分而治之的思想建立起来的. 所谓的分而治之,也就是将一个数据规模为N的数据集,分解为两个规模大小差不多的数据集(n/2),然而分别处理这两个更小的问题,就相当于解决 ...

  5. 排序算法Java实现(归并排序)

    算法描述:对于给定的一组记录,首先将每两个相邻的长度为1的子序列进行归并,得到 n/2(向上取整)个长度为2或1的有序子序列,再将其两两归并,反复执行此过程,直到得到一个有序序列. package s ...

  6. 排序算法Nb三人组-归并排序

    归并排序只能对两个已经有序的列表进行合并排序,所以要我们自己创建出两个有序列表.最后在进行合并. def merge2list(li1, li2): li = [] i = 0 j = 0 while ...

  7. 简易版的TimSort排序算法

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. 简易版本TimSort排序算法原理与实现 TimSort排序算法是Python和Ja ...

  8. [Data Structure & Algorithm] 八大排序算法

    排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...

  9. JS家的排序算法

    由于浏览器的原生支持(无需安装任何插件),用JS来学习数据结构和算法也许比c更加便捷些.因为只需一个浏览器就能啪啪啪的调试了.比如下图我学习归并排序算法时,只看代码感觉怎么都理解不了,但是结合chro ...

随机推荐

  1. Scrapy笔记07- 内置服务

    Scrapy笔记07- 内置服务 Scrapy使用Python内置的的日志系统来记录事件日志. 日志配置 LOG_ENABLED = true LOG_ENCODING = "utf-8&q ...

  2. Spring Cloud微服务安全实战_00_前言

    一.前言: 一直以来对服务安全都很感兴趣,所以就学习.这是学习immoc的 jojo老师的 <Spring Cloud微服务安全实战课程>的笔记,讲的很好. 课程简介:  二.最终形成的架 ...

  3. LeetCode 622. Design Circular Queue

    原题链接在这里:https://leetcode.com/problems/design-circular-queue/ 题目: Design your implementation of the c ...

  4. zzulioj - 2558 数字的差值

    首先感谢抱抱熊dalao的题解,提供了一种比较简单的思路.[抱抱熊dalao的题解](https://note.youdao.com/ynoteshare1/index.html?id=52f087d ...

  5. [FJOI2018]所罗门的宝藏

    大概是最后一篇题解,其实只是想颓废一下打个故事 据古代传说记载,所罗门王即是智慧的代表,又是财富的象征.他建立了强大而富有的国家,聚集了大批的黄金象牙和钻石,并把这些价值连城的珍宝藏在一个神秘的地方, ...

  6. java信号量

    维基百科解释的信号量概念如下 信号量(英语:semaphore)又称为信号标,是一个同步对象,用于保持在0至指定最大值之间的一个计数值.当线程完成一次对该semaphore对象的等待(wait)时,该 ...

  7. UDF——文件编码造成UDF编译失败

    有时候我们觉得我们的代码写得很正确的,但是在Fluent当中编译的时候一直编译不通过,提示我们错误,我们根据Fluent当中的错误提示去找到源代码中对应的行,却发现没有错误提示当中的问题,出现这个问题 ...

  8. 【07月01日】A股滚动市净率PB历史新低排名

    2010年01月01日 到 2019年07月01日 之间,滚动市净率历史新低排名. 上市三年以上的公司,2019年07月01日市净率在30以下的公司. 来源:A股滚动市净率(PB)历史新低排名. 1 ...

  9. js密码加密

    1.base64加密:在页面中引入base64.js文件,调用方法为: <!DOCTYPE HTML> <html> <head> <meta charset ...

  10. 小程序接口无法传递session校验验证码

    今天在写接口的时候发现一个问题,我用apiaaz测试一切正常,但是从小程序接口请求验证码,一直验证失败. 最开始用的图形验证码,查阅了不少资料,最后怀疑是cookie的问题,解决无果,换成了短信验证码 ...