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

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

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

说明几点:

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. 洛谷P1578 奶牛牧场(悬线法思想)

    题目 悬线法的思想--即扫描线的思想,每个矩阵必定是由两个障碍来构成左右边界或者上下边界. 如果此两个障碍组成了左右边界,枚举这两个障碍中途更新这两个障碍之间的矩阵上下边界,并且更新最大值. 考虑如何 ...

  2. 批量转换文件字符编码(GBK转UTF-8)

    今天收到一份代码,拖到IDE中发现乱码,看来下编码是GBK的(

  3. 【BigData】Java基础_ArrayList的使用

    ArrayList概述 ArrayList底层使用的是数组.是List的可变数组实现,这里的可变是针对List而言,而不是底层数组. 数组有自身的特点,不变性,一旦数组被初始化,那么其长度就固定了,不 ...

  4. ##C++ format 格式化字符串

    C++ format 格式化字符串实现方式 1. http://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprint ...

  5. jquery根据选择器进行页面赋值,封装赋值方法

    可以进行文本框赋值,文本域赋值,下拉列表赋值,单选框赋值,多选框赋值, 传入对象,可以根据元素name进行比对赋值,不用每个进行单独赋值 <!DOCTYPE html> <html ...

  6. 自动签发https证书工具 cert manager

    最近cert manager进行升级,不再支持0.11以下的版本了,所以进行升级.但是发现不能直接通过更改镜像版本来升级,在Apps里的版本也是旧版本,部署后发现不支持,于是自已动手,根据文档整理了一 ...

  7. concurrent(四)Condition

    参考文档:Java多线程系列--“JUC锁”06之 Condition条件:http://www.cnblogs.com/skywang12345/p/3496716.html Condition介绍 ...

  8. 【Docker】涨姿势,深入了解Dockerfile 中的 COPY 与 ADD 命令

    参考资料:https://www.cnblogs.com/sparkdev/p/9573248.html Dockerfile 中提供了两个非常相似的命令 COPY 和 ADD,本文尝试解释这两个命令 ...

  9. WebBrowser内存泄露

    使用WebBrowser控件开发的程序,占用内存会随着时间不停增长,最终内存溢出导致崩溃.究其原因是由于其自身的缺陷造成的.每一次加载新页面,WebBrowser就会多占用10-20M内存,有资料说是 ...

  10. 停止IIS服务

    1 第一步 停止 World Wide Web Publishing Service     这个是W3C服务 2 第二部 停止 IIS Admin Service  这个IIS元数据管理服务