小小c#算法题 - 8 - 归并排序 (Merging Sort)
“归并”的含义是将两个或两个以上的有序序列组合成一个新的有序序列。这个“归并”可以在O(n+m)的数量级上实现,但这同时也需要O(n+m)的空间复杂度。具体为:首先分配一个新的长度为n+m的空序列,然后对于序列1(长度为n),序列2(长度为m),从每个序列的第一个元素开始比较,将较小的元素放入新的序列,然后较小元素原来所在序列的下标加1,这样一直比较下去,最终把这两个序列有序的放入新的序列中。在2-路归并排序中,这里的序列1,序列2表现为待排序列的两个相邻子序列。
2-路归并排序的定义:假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2(上取整)个长度为2或1的有序子序列;再两两归并,......,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2-路归并排序。
那么可以看出,2-路归并排序中的核心操作是将一维数组中相邻的两个有序子序列归并为一个有序序列,代码如下:
传入一个数组,将这个数组中的两个有序子序列(low ~ middle, middle + 1 ~high)合并成一个有序的子序列。先把序列copy一份,用来后面比较元素使用。
static void Merge(int[] numbers, int low, int middle, int high)
{
int[] temp = new int[numbers.Length];
numbers.CopyTo(temp, );
int index = low;
int m = middle + ;
while (low <= middle && m <= high)
{
if (temp[low] <= temp[m])
{
numbers[index++] = temp[low++];
}
else
{
numbers[index++] = temp[m++];
}
} // 比较循环结束后,左边(低位)子序列有剩余元素的情况
while (low <= middle)
{
numbers[index++] = temp[low++];
} // 比较循环结束后,右边(高位)子序列有剩余元素的情况
while (m <= high)
{
numbers[index++] = temp[m++];
}
}
上面核心操作的算法已经实现了,下面就是怎么通过调用上述算法来对序列进行排序了。这里采用了递归的思想,当对一个序列进行排序时,分别对其左,右子序列进行排序(一般从中间划分),左,右子序列有序后,调用Merger方法合并这两个子序列,得到整个的有序序列。递归停止的条件是序列长度只为1的时候。代码如下:
static void MergeSort(int[] numbers, int low, int high)
{
// low == high时序列长度为1,是停止递归的条件
if (low != high)
{
int middle = (low + high) / ;
MergeSort(numbers, low, middle);
MergeSort(numbers, middle + , high);
Merge(numbers, low, middle, high);
}
}
为了方便调用,对MergeSort又封装一次:
static void MSort(int[] numbers)
{
MergeSort(numbers, , numbers.Length - );
}
下面是对MergeSort方法的调用(这个例子使用控件台应用程序类型):
static void Main(string[] args)
{
int[] numbers = { , , , , , , , , , , , , };
MSort(numbers); foreach (int i in numbers)
{
Console.Write(i.ToString() + " ");
}
}
归并排序是稳定的排序,Merge方法的时间复杂度为O(n), 要实现排序,需调用logn次Merge方法,所以归并排序的时间复杂度为O(n*logn)。由于排序时需要额外的临时序列的copy,所以空间复杂度为O(n),这也是归并排序的缺点。
一个可以优化的地方:
Merger方法中,每次都要copy一整份序列。但其实只要copy其中的要比较的两个子序列中的元素即可,所以有优化代码如下:
static void Merge(int[] numbers, int low, int middle, int high)
{
int[] temp = new int[high - low + ];
for (int i = low, j = ; i <= high; i++)
{
temp[j++] = numbers[i];
} int index = low;
middle -= low;
high -= low;
low = ;
int m = middle + ;
while (low <= middle && m <= high)
{
if (temp[low] <= temp[m])
{
numbers[index++] = temp[low++];
}
else
{
numbers[index++] = temp[m++];
}
} while (low <= middle)
{
numbers[index++] = temp[low++];
} while (m <= high)
{
numbers[index++] = temp[m++];
}
}
小小c#算法题 - 8 - 归并排序 (Merging Sort)的更多相关文章
- 小小c#算法题 - 9 - 基数排序 (Radix Sort)
基数排序和前几篇博客中写到的排序方法完全不同.前面几种排序方法主要是通过关键字间的比较和移动记录这两种操作来实现排序的,而实现基数排序不需要进行记录项间的比较.而是把关键字按一定规则分布在不同的区域, ...
- 小小c#算法题 - 7 - 堆排序 (Heap Sort)
在讨论堆排序之前,我们先来讨论一下另外一种排序算法——插入排序.插入排序的逻辑相当简单,先遍历一遍数组找到最小值,然后将这个最小值跟第一个元素交换.然后遍历第一个元素之后的n-1个元素,得到这n-1个 ...
- 归并排序(Merging Sort)
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 数据结构 - 归并排序(merging sort)
归并排序(merging sort): 包含2-路归并排序, 把数组拆分成两段, 使用递归, 将两个有序表合成一个新的有序表. 归并排序(merge sort)的时间复杂度是O(nlogn), 实际效 ...
- 小小c#算法题 - 11 - 二叉树的构造及先序遍历、中序遍历、后序遍历
在上一篇文章 小小c#算法题 - 10 - 求树的深度中,用到了树的数据结构,树型结构是一类重要的非线性数据结构,树是以分支关系定义的层次结构,是n(n>=0)个结点的有限集.但在那篇文章中,只 ...
- 数据结构 - 归并排序(merging sort) 具体解释 及 代码
归并排序(merging sort) 具体解释 及 代码 本文地址: http://blog.csdn.net/caroline_wendy 归并排序(merging sort): 包括2-路归并排序 ...
- 排序算法二:归并排序(Merge sort)
归并排序(Merge sort)用到了分治思想,即分-治-合三步,算法平均时间复杂度是O(nlgn). (一)算法实现 private void merge_sort(int[] array, int ...
- 小小c#算法题 - 6 - 快速排序 (QuickSort)
快速排序是排序算法中效率比较高的一种,也是面试常被问到的问题. 快速排序(Quick Sort)是对冒泡排序的一种改进.它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字 ...
- 小小c#算法题 - 12 - Joseph Circle(约瑟夫环)
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数(从1开始报数),数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又 ...
随机推荐
- storm入门原理介绍
转自:http://www.cnblogs.com/wuxiang/p/5629138.html 1.hadoop有master与slave,Storm与之对应的节点是什么?2.Storm控制节点上面 ...
- 洛谷 P2822 组合数问题
题目描述 组合数C_n^mCnm表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法.根据组合数的 ...
- java中static的学习
1.static引入: 通常来说,当创建一个类是,就是在描述那个类的对象的外观与行为.除非用new创建那个类的对象,否则实际并未获取任何对象.当执行new来创建对象时,数据存储空间才被分配,七方法才供 ...
- es6字符串的扩展学习笔记
1. 传统上,JavaScript只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中.ES6又提供了三种新方法. includes():返回布尔值,表示是否找到了参数字符串. st ...
- django1.7+nginx1.4.4的static配置
静态文件指像css,js,images之类的文件. 1.工程配置setting.py STATIC_URL = /static/ STATIC_ROOT = /home/www/winingcpi/s ...
- 使用批处理自动发布IIS站点,基于IIS7及以上
经过研究,终于使用批处理解决了站点发布步骤多的问题. 完整批处理如下: @set "sitePath=%~dp0" @echo 新建程序池 @C:\Windows\System32 ...
- 一些js和JQuery的方法
取值填值: js: get-- innerText, innerHTML, value; set-- innerText=?, innerHTML=?, value=?; JQuery: get-- ...
- java代码异常普通的====
总结:对于各种流类, package com.da; //包括运行异常,和非运行异常 import java.io.*; public class ryl { public static void m ...
- Java事务的原理与应用
Java事务的原理与应用 一.什么是Java事务 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (isolation ...
- PDM后续处理-驼峰规则、清除约束、外键改名
Option Explicit ValidationMode = True InteractiveMode = im_Batch Dim mdl '当前model '获取当前活 ...