归并排序(Merge Sort)是利用"归并"技术来进行排序。归并是指将若干个已排序的子文件合并成一个有序的文件。归并排序有两种方式:1): 自底向上的方法 2):自顶向下的方法

1、 自底向上的方法
(1) 自底向上的基本思想
     自底向上的基本思想是:第1趟归并排序时,将待排序的文件R[1..n]看作是n个长度为1的有序子文件,将这些子文件两两归并,若n为偶数,则得到n/2个长度为2的有序子文件;若n为奇数,则最后一个子文件轮空(不参与归并)。故本趟归并完成后,前n/2 - 1个有序子文件长度为2,但最后一个子文件长度仍为1;第2趟归并则是将第1趟归并所得到的n/2个有序的子文件两两归并,如此反复,直到最后得到一个长度为n的有序文件为止。
     上述的每次归并操作,均是将两个有序的子文件合并成一个有序的子文件,故称其为"二路归并排序"。类似地有k(k>2)路归并排序。

2、自顶向下的方法(本文主要介绍此种方法,下面的文字都是对此种方法的解读)

(1) 自顶向下的基本思想
     采用分治法进行自顶向下的算法设计,形式更为简洁。
     自顶向下的归并排序:是利用递归和分而治之的技术将数据序列划分成为越来越小的半子表,再对半子表排序,最后再用递归步骤将排好序的半子表合并成为越来越大的有序序列,归并排序包括两个步骤,分别为:

1)划分子表

2)合并半子表

(1)分治法的三个步骤
     设归并排序的当前区间是R[low..high],分治法的三个步骤是:
①分解:将当前区间一分为二,即求分裂点
②求解:递归地对两个子区间R[low..mid]和R[mid+1..high]进行归并排序;
③组合:将已排序的两个子区间R[low..mid]和R[mid+1..high]归并为一个有序的区间R[low..high]。
  递归的终结条件:子区间长度为1(一个记录自然有序)。

如下演示递归的整个过程:

递归便是深度遍历(如下由左至右进行遍历):假设有这样的一列数组{9,8,7,6,5,4,3,2,1}进行划分的顺序如下:

{9,8,7,6,5,4,3,2,1} --> {9,8,7,6,5},{4,3,2,1}

{9,8,7,6,5} --> {9,8,7},{6,5}

{9,8,7} --> {9,8},{7}

{9,8} --> {9},{8}

{6,5} -->{6},{5}

{4,3,2,1} --> {4,3},{2,1}

{4,3} -->{4},{3}

{2,1} -->{2},{1}

当深度划分到左右数组都只剩1个元素的时候,进行上述逆序的合并:

{9},{8} --> {8,9} 然后和 {7} --> {7,8,9}

{6},{5} --> {5,6}    然后 {7,8,9}和{5,6} --> {5,6,7,8,9}

{2},{1} --> {1,2}

{4},{3} --> {3,4}   然后 {1,2}和 {3,4} --> {1,2,3,4}

最终{5,6,7,8,9}和{1,2,3,4} --> {1,2,3,4,5,6,7,8,9}

 

具体实现代码如下所示:

        //归并排序(目标数组,子表的起始位置,子表的终止位置)        private static void MergeSortFunction(int[] array, int first, int last)        {try            {if (first < last)   //子表的长度大于1,则进入下面的递归处理                {int mid = (first + last) / 2;   //子表划分的位置                    MergeSortFunction(array, first, mid);   //对划分出来的左侧子表进行递归划分                    MergeSortFunction(array, mid + 1, last);    //对划分出来的右侧子表进行递归划分                    MergeSortCore(array, first, mid, last); //对左右子表进行有序的整合(归并排序的核心部分)                }            }catch (Exception ex)            { }        }

//归并排序的核心部分:将两个有序的左右子表(以mid区分),合并成一个有序的表        private static void MergeSortCore(int[] array, int first, int mid, int last)        {try            {int indexA = first; //左侧子表的起始位置                int indexB = mid + 1;   //右侧子表的起始位置                int[] temp = new int[last + 1]; //声明数组(暂存左右子表的所有有序数列):长度等于左右子表的长度之和。                int tempIndex = 0;while (indexA <= mid && indexB <= last) //进行左右子表的遍历,如果其中有一个子表遍历完,则跳出循环                {if (array[indexA] <= array[indexB]) //此时左子表的数 <= 右子表的数                    {                        temp[tempIndex++] = array[indexA++];    //将左子表的数放入暂存数组中,遍历左子表下标++                    }else//此时左子表的数 > 右子表的数                    {                        temp[tempIndex++] = array[indexB++];    //将右子表的数放入暂存数组中,遍历右子表下标++                    }                }//有一侧子表遍历完后,跳出循环,将另外一侧子表剩下的数一次放入暂存数组中(有序)                while (indexA <= mid)                {                    temp[tempIndex++] = array[indexA++];                }while (indexB <= last)                {                    temp[tempIndex++] = array[indexB++];                }

//将暂存数组中有序的数列写入目标数组的制定位置,使进行归并的数组段有序                tempIndex = 0;for (int i = first; i <= last; i++)                {                    array[i] = temp[tempIndex++];                }            }catch (Exception ex)            { }        }

对于N个元素的数组来说, 如此划分需要的层数是以2为底N的对数, 每一层中, 每一个元素都要复制到结果数组中, 并复制回来, 所以复制2N次, 那么对于归并排序,它的时间复杂度为O(N*logN), 而比较次数会少得多, 最少需要N/2次,最多为N-1次, 所以平均比较次数在两者之间. 它的主要问题还是在于在内存中需要双倍的空间.

转载于:https://www.cnblogs.com/kloseking/p/3165710.html

归并排序算法(C#实现)相关推荐

  1. 【java排序】 归并排序算法、堆排序算法

    一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...

  2. JavaScript实现MergeSort归并排序算法(附完整源码)

    JavaScript实现MergeSort归并排序算法(附完整源码) Comparator.js完整源代码 Sort.js完整源代码 MergeSort.js完整源代码 Comparator.js完整 ...

  3. C语言merge sort归并排序算法(附完整源码)

    C语言merge sort归并排序算法 merge sort归并排序算法的完整源码(定义,实现) merge sort归并排序算法的完整源码(定义,实现) #ifndef MERGE_SORT_H # ...

  4. python 归并排序算法_python基本算法之实现归并排序(Merge sort)

    0.前言 评判一个算法的好坏的标准: 时间复杂度 空间复杂度 1.归并排序算法是什么? 冒泡排序(Bubble Sort)是一种建立在归并操作上面的一种有效的排序算法,由John von neuman ...

  5. 排序算法:归并排序算法实现及分析

    归并排序算法介绍 归并排序(Merging Sort)就是利用归并的思想实现排序的放.它的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个 ...

  6. 算法竞赛——归并排序算法

    算法竞赛--归并排序算法 分治法 划分问题:把序列分成元素个数尽量相等的两半 递归求解:把两半元素分别排序 合并问题:把两个有序表合并成一个 借鉴RuJia的精妙的合并过程 void merges2( ...

  7. 有序序列的二分查找、冒泡排序、归并排序算法实战解析

    本节开始讲解一下几个简单的算法,原理都在那本书上,大家自己看吧,我就不做搬运工了,这里不同的是,我把vector接口函数单独拿出来进行测试了,深深的体会到算法的奥妙之处,等你深入理解了你会情不自禁拍案 ...

  8. 第十五周 项目三 归并排序算法的改进

    /* * Copyright (c)2017,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名称:项目3.cpp * 作 者:孙仁圆 * 完成日期:2017年12 ...

  9. C++ 不知算法系列之聊聊希尔、归并排序算法中的分治哲学

    1. 前言 排序算法中,冒泡.插入.选择属于相类似的排序算法,这类算法的共同点:通过不停地比较,再使用交换逻辑重新确定数据的位置. 希尔.归并.快速排序算法也可归为同一类,它们的共同点都是建立在分治思 ...

  10. 排序算法系列:归并排序算法

    概述 上一篇我们说了一个非常简单的排序算法--选择排序.其复杂程序完全是冒泡级的,甚至比冒泡还要简单.今天要说的是一个相对比较复杂的排序算法--归并排序.复杂的原因不仅在于归并排序分成了两个部分进行解 ...

最新文章

  1. R语言原生hist函数绘制直方图实战
  2. 《用广义CNOT门产生质数幂维的图态》
  3. activity堆栈式管理
  4. initramfs下启动linux_和菜鸟一起学linux之initramfs方式启动
  5. matlab华侨大学,闫铮-华侨大学-信息科学与工程学院
  6. csrf-token
  7. 【渝粤题库】广东开放大学 经济学基础 形成性考核
  8. DOM基础操作(二)
  9. SAP License:员工离职分析
  10. Spring框架(IoC、AOP面向接口切面)
  11. linux虚拟主机用织梦,织梦程序用什么虚拟主机很服务器好
  12. java虚拟机是什么?
  13. 管螺纹如何标注_螺纹知识,这一次搞全了!
  14. 软件项目经理应具备的素质和条件_项目经理应具备的素质与能力
  15. xp系统更改计算机名c盘,c盘满了怎么办,小编教你电脑xp的c盘满了怎么办
  16. PAT 1010 月饼
  17. table制作课程表案例
  18. USB设备仿真框架设计指南——11.在托管代码中开发DSF应用程序
  19. 20200428 线程安全(上)--彻底搞懂volatile关键字
  20. Mulitisim频率计设计

热门文章

  1. 快速解决 Android SDK Manager 无法下载或者下载速度慢
  2. React开发(147):开发注意
  3. 前端学习(3248):react的生命周期getSnapBeforeUpdate举例
  4. [html] 如何在页面上显示Emoji表情?
  5. [vue] 说说你使用vue过程中遇到的问题(坑)有哪些,你是怎么解决的?
  6. [css] 使用css实现蒙版的效果
  7. 工作173:一级控制二级菜单的变化
  8. 工作141:map形成数组
  9. 前端学习(1939)vue之电商管理系统电商系统之完成全部功能
  10. 前端学习(1266):axios的常见api