1.介绍

归并排序(MergeSort)是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分(divide)成一些小的问题然后递归求解,

而治(conquer)的阶段则将分的阶段得到的各答案“修补”在一起,即分而治之)

2.示意图

 说明:可以看到这种结构很像一颗完全二叉树,可以采用递归和循环迭代的方式去实现,分阶段可以理解为就是递归拆分子序列的过程

合并相邻有序子序列

再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,

要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤

 

3.实例

把数组[8,4,5,7,1,3,6,2]使用归并排序完成排序

    public class MergeSort
{
public static void Test()
{
int[] arr = { , , , , , , , }; int[] temp = new int[arr.Length]; Sort(arr,,arr.Length-,temp); Console.WriteLine(string.Join(",",arr));
} /// <summary>
/// 分+合方法
/// </summary>
/// <param name="arr"></param>
/// <param name="left"></param>
/// <param name="right"></param>
/// <param name="temp"></param>
private static void Sort(int[] arr,int left,int right,int[] temp)
{
if (left<right)
{
//中间索引
int mid = (left + right) / ; //向左递归进行分解
Sort(arr, left, mid, temp); //向右递归进行分解
Sort(arr, mid + , right, temp); //到合并
Merge(arr,left,mid,right,temp);
}
} /// <summary>
/// 合并方法
/// </summary>
/// <param name="arr">排序的原始数组</param>
/// <param name="left">左边有序序列的初始索引</param>
/// <param name="mid">中间索引</param>
/// <param name="right">右边索引</param>
/// <param name="temp">做中转数组</param>
private static void Merge(int[] arr, int left, int mid, int right, int[] temp)
{
int i = left; //初始化i,左边有序序列的初始化索引 int j = mid + ; //初始化j,右边有序序列的初始化索引 int t = ; //指向temp数组的当前索引 //(一)
//先把左右两边(有序)的数据按照规则填充到temp数组
//直到左右两边的有序序列,有一边处理完成为止
while (i <= mid && j <= right)
{
//如果左边的有序序列的当前元素,小于或者等于右边有序序列的当前元素
//即将左边的当前元素,填充到temp数组
//然后t++,i++
if (arr[i] <= arr[j])
{
temp[t] = arr[i]; t += ; i += ;
}
//反之,将右边有序序列的当前元素,填充到temp数组
else
{
temp[t] = arr[j]; t++; j++;
}
}
//(二)
//把有剩余数据的一边的数据依次全部填充到temp
while (i <= mid)
{
//左边的有序序列还有剩余的元素,就全部填充到temp
temp[t] = arr[i]; t++; i++;
} while (j <= right)
{
temp[t] = arr[j]; t++; j++;
}
//(三)
//将temp数组的元素拷贝到arr,并不是每次都拷贝所有
t = ; int tempLeft = left; while (tempLeft <= right) //第一次合并 tempLeft=0,right=1 第二次 tempLeft=2 right=3;
{
arr[tempLeft] = temp[t]; t++; tempLeft++;
} }
}

结果图

C#数据结构与算法系列(二十三):归并排序算法(MergeSort)的更多相关文章

  1. WPF入门教程系列二十三——DataGrid示例(三)

    DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...

  2. Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十三】

    <Web 前端开发精华文章推荐>2014年第2期(总第23期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  3. 【数据结构】 最小生成树(二)——kruskal算法

    上一期说完了什么是最小生成树,这一期咱们来介绍求最小生成树的算法:kruskal算法,适用于稀疏图,也就是同样个数的节点,边越少就越快,到了数据结构与算法这个阶段了,做题靠的就是速度快,时间复杂度小. ...

  4. CRC16算法之二:CRC16-CCITT-XMODEM算法的java实现

    CRC16算法系列文章: CRC16算法之一:CRC16-CCITT-FALSE算法的java实现 CRC16算法之二:CRC16-CCITT-XMODEM算法的java实现 CRC16算法之三:CR ...

  5. 数据结构与算法系列----最小生成树(Prim算法&amp;Kruskal算法)

     一:Prim算法       1.概览 普里姆算法(Prim算法).图论中的一种算法.可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中.不但包含了连通图里的全部顶点(英语:Ve ...

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

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

  7. JVM系列二(垃圾收集算法).

    一.标记-清除算法(Mark-Sweep) 这种算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. Mar ...

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

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

  9. 排序算法系列:选择排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)

    在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍: 原理讲不清,混乱 啰嗦 图和文对不上 不可用,甚至代码还出错 我总结一个清晰不罗嗦版: 原理: 从数组头元素索引i开始,寻找后面最小的值(比i位 ...

  10. JVM-GC算法(二)-复制算法&&标记整理算法

    这次我和各位分享GC最后两种算法,复制算法以及标记/整理算法.上一篇在讲解标记/清除算法时已经提到过,这两种算法都是在此基础上演化而来的,究竟这两种算法优化了之前标记/清除算法的哪些问题呢? 复制算法 ...

随机推荐

  1. cc40a_demo_Cpp_智能指针c++_txwtech

    //40_21days_Cpp_智能指针c++_cc40a_demo.cpp_txwtech //智能指针.auto_ptr类//*常规指针-容易产生内存泄漏,内存被占满,程序就死机,或者系统死机// ...

  2. 【SEED Labs】DNS Rebinding Attack Lab

    Lab Overview 实验环境下载:https://seedsecuritylabs.org/Labs_16.04/Networking/DNS_Rebinding/ 在这个实验中模拟的物联网设备 ...

  3. Beta冲刺<7/10>

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第七天(05.25) 作业正文 如下 其他参考文献 ... B ...

  4. linux kernel update

    linux内核升级 最近HW行动,报出来的linux系统内核漏洞,环境中全部是2.6.32-431.el6.x86_64的主机,需要全部升级到754版本,这也是第一次进行内核升级操作. 先找了一台和生 ...

  5. oracle自定义split分割函数

    函数如下: create or replace FUNCTION fn_rme_split(p_str IN VARCHAR2, p_delimiter IN VARCHAR2) RETURN rme ...

  6. SpringBoot — HelloWorld开发部署

    springboot官方推荐使用jdk1.8 一.配置pom.xml 二.Application.java 三.HelloController.java 四.项目运行: Application.jav ...

  7. mysql语句基本练习

    select ename,job from emp where job in ('MANAGER','ANALYET','SALESMAN') 1.查询出工作岗位为MANAGER.ANALYST.SA ...

  8. 当我们创建HashMap时,底层到底做了什么?

    jdk1.7中的底层实现过程(底层基于数组+链表) 在我们new HashMap()时,底层创建了默认长度为16的一维数组Entry[ ] table.当我们调用map.put(key1,value1 ...

  9. c# 线程的优先级

    前言 有时候我们希望某个线程更加重要,希望让其先运行的话.c#为我们提供了线程修改优先级.但是这样的效果有多大呢? 正文 直接放代码: static void Main(string[] args) ...

  10. 好看的UI框架

    一.Web 1.semantic-ui: https://semantic-ui.com/elements/divider.html 二.H5 1.BUI: http://www.easybui.co ...