算法實例-C#-歸併排序-MergeSort
# 算法实例 #
排序算法Sort
歸併排序MergeSort
算法說明
- 歸併的思路是任意兩個元素可以比較大小,那麼任意兩個有序的元素集合也可以通過比較大小的方式歸併成一個有序的元素集合
- 任何的無序元素集合可以拆分的最小的可比較單位是元素本身,例如List list = new List() { 23, 42, 4, 16, 8, 23, 15, 3, 9, 55, 0, 23, 34, 12, 2, 46, 25, 25 };可以拆分到最小的元素為{{23},{42},{4},{16},{8},{23},{15},{3},{9},{55},{0},{23},{34},{12},{2},{46},{25},{25}},如果我們將這些元素組合兩兩比較就可以得到新的一組有序的元素組合{{23,24},{4,16},{8,23},{3,15},{9,55},{0,23},{12,34},{2,46},{25,25}}
- 對於上訴的元素集合進行比較后的有序元素集合,如下圖
最基本元素(即不可拆分最小元素集合)

第一次兩兩歸併

第二次兩兩歸併

第三次兩兩歸併

第四次兩兩歸併

最終合一的歸併

算法步驟
1.我的算法中使用隊列來作為容器容納元素,最小可比較單位也就是隊列中只有壹個元素,同時在外層也使用隊列來分別容納歸併的隊列即使用 Queue<Queue<T>> 的結構,其中 Queue<Queue<T>>是壹個歸併隊列的集合(如[{23,24},{4,16}]),Queue<T>是有序元素的集合(如{23,24})
2.遞歸的跳出條件是,歸併完成即Queue<Queue<T>>的元素個數Count為壹.且每一次遞歸完成一次兩兩歸併.
3.使用隊列的好處在於,可以使用Peek()和Dequeue()方法來確定參與一次歸併的隊列Queue<T> _tempLeft和Queue<T> _tempRight哪一個先出對歸並到新的有序集合中.
代碼示例
public static class MergeSorterA
{
/// <summary>
/// Public merge-sort API
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection"></param>
/// <param name="comparer"></param>
public static void MergeSortA<T>(this Queue<T> collection, Comparer<T> comparer = null)
{
comparer = comparer ?? Comparer<T>.Default;
Queue<Queue<T>> _queue = new Queue<Queue<T>>();
while (collection.Count !=0 )
{
Queue<T> _temp = new Queue<T>();
_temp.Enqueue(collection.Dequeue());
_queue.Enqueue(_temp);
}
_queue.InternalMergeSortA(comparer);
foreach (var item in _queue.Dequeue())
{
collection.Enqueue(item);
}
}
/// <summary>
/// Implements the recursive merge-sort algorithm
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collectionQueue"></param>
/// <param name="comparer"></param>
private static void InternalMergeSortA<T>(this Queue<Queue<T>> collectionQueue, Comparer<T> comparer)
{
Queue<Queue<T>> _listQueue = new Queue<Queue<T>>();
while (collectionQueue.Count != 0)
{
Queue<T> _queue = new Queue<T>();
Queue<T> _tempLeft = new Queue<T>();
Queue<T> _tempRight = new Queue<T>();
_tempLeft = collectionQueue.Dequeue();
//make sure _tmepLeft is not the ends
if (collectionQueue.Count != 0)
{
_tempRight = collectionQueue.Dequeue();
}
int _length = _tempLeft.Count + _tempRight.Count;
for (int i = 0; i < _length; i++)
{
if (_tempLeft.Count > 0 && _tempRight.Count > 0)
{
_queue.Enqueue(comparer.Compare(_tempLeft.Peek(), _tempRight.Peek()) <= 0 ? _tempLeft.Dequeue() : _tempRight.Dequeue());
}
else if (_tempLeft.Count > 0)
{
_queue.Enqueue(_tempLeft.Dequeue());
}
else if (_tempRight.Count > 0)
{
_queue.Enqueue(_tempRight.Dequeue());
}
}
_listQueue.Enqueue(_queue);
}
if (_listQueue.Count > 1)
{
_listQueue.InternalMergeSortA(comparer);
}
collectionQueue.Clear();
foreach (var item in _listQueue)
{
collectionQueue.Enqueue(item);
}
}
}
測試用例
[TestMethod]
public void TestMethod3()
{
List<int> list = new List<int>() { 23, 42, 4, 16, 8, 23, 15, 3, 9, 55, 0, 23, 34, 12, 2, 46, 25, 25 };
Queue<int> _queue = new Queue<int>(list);
_queue.MergeSortA();
Assert.Fail();
}
算法實例-C#-歸併排序-MergeSort的更多相关文章
- 算法實例-C#-信箱排序-PigeonHoleSort
# 算法实例 # 排序算法Sort 信箱排序PigeonHoleSort https://en.wikipedia.org/wiki/Pigeonhole_sort 算法說明 1.信箱算法使用一個完整 ...
- 七内部排序算法汇总(插入排序、Shell排序、冒泡排序、请选择类别、、高速分拣合并排序、堆排序)
写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的随意序列,又一次排列成一个按keyword有序的序列.因此排序掌握各种排序算法很重要. 对以下介绍的各个排序,我们假定全部排 ...
- 《算法4》2.1 - 选择排序算法(Selection Sort), Python实现
选择排序算法(Selection Sort)是排序算法的一种初级算法.虽然比较简单,但是基础,理解了有助于后面学习更高深算法,勿以勿小而不为. 排序算法的语言描述: 给定一组物体,根据他们的某种可量化 ...
- JavaScript 数据结构与算法之美 - 十大经典排序算法汇总(图文并茂)
1. 前言 算法为王. 想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手:只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 ...
- SpringMVC常用注解實例詳解3:@ResponseBody
我的開發環境框架: springmvc+spring+freemarker開發工具: springsource-tool-suite-2.9.0JDK版本: 1.6.0_29tomcat ...
- SpringMVC常用注解實例詳解2:@ModelAttribute
我的開發環境框架: springmvc+spring+freemarker開發工具: springsource-tool-suite-2.9.0JDK版本: 1.6.0_29tomcat ...
- RTX的api開發實例
RTX的api開發實例 最近接觸了RTX的接口開發部份,RTX其实有很多玩法,除了可以用自帶的客戶端發消息之外還可以用PHP調用API的方式來做一些事情,下邊整理了一下分享給大家 值得提醒的是这些接口 ...
- 簡單SQL存儲過程實例
簡單SQL存儲過程實例 摘自:http://blog.csdn.net/libra6956/article/details/5589173 实例1:只返回单一记录集的存储过程. 银行存款表(bankM ...
- C++ Primer : 第十章 : 泛型算法 之 只读、写和排序算法
大多数算法都定义在<algorithm>头文件里,而标准库还在头文件<numeric>里定义了一组数值泛型算法,比如accumulate. ● find算法,算法接受一对迭代 ...
随机推荐
- Lucene系列-facet
1.facet的直观认识 facet:面.切面.方面.个人理解就是维度,在满足query的前提下,观察结果在各维度上的分布(一个维度下各子类的数目). 如jd上搜“手机”,得到4009个商品.其中品牌 ...
- C#入门基础三
封装:简化用户接口,隐藏实现细节. get{return 属性值:} set{属性值 = value:} 继承:子类继承父类所有非私有成员.继承具有传递性,单根性. 隐式继承:用引号(:)实现. 显示 ...
- javascript之-深入事件机制
作者:yuyuyu链接:https://zhuanlan.zhihu.com/p/24620643来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1.1 事件绑定的方式 ...
- Beats数据采集---Packetbeat\Filebeat\Topbeat\WinlogBeat使用指南
Beats是elastic公司的一款轻量级数据采集产品,它包含了几个子产品: packetbeat(用于监控网络流量). filebeat(用于监听日志数据,可以替代logstash-input-fi ...
- hibernate(八) Hibernate检索策略(类级别,关联级别,批量检索)详解
序言 很多看起来很难的东西其实并不难,关键是看自己是否花费了时间和精力去看,如果一个东西你能看得懂,同样的,别人也能看得懂,体现不出和别人的差距,所以当你觉得自己看了很多书或者学了很多东西的时候,你要 ...
- 【WP 8.1开发】手机客户端应用接收推送通知
上一篇文章中,已经完成了用于发送通知的服务器端,接下来我们就用这个服务端来测试一下. 在开始测试之前,我们要做一个接收通知的WP应用. 1.启动VS Express for Windows,新建项目, ...
- 深入理解CSS中的长度单位
前面的话 本文分为绝对长度单位和相对长度单位来介绍CSS中的长度单位的主要知识 绝对长度单位 绝对长度单位代表一个物理测量 像素px(pixels) 在web上,像素px是典型的度量单位,很多其他长度 ...
- 深入理解javascript作用域系列第四篇——块作用域
× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用 ...
- mysql load data infile的使用 和 SELECT into outfile备份数据库数据
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE t ...
- Chrome 控制台指南
转自:http://blog.jobbole.com/76985/ Chrome的开发者工具已经强大到没朋友的地步了,特别是其功能丰富界面友好的console,使用得当可以有如下功效: 更高「逼格」更 ...