算法實例-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算法,算法接受一对迭代 ...
随机推荐
- Linux网络编程系列-TCP传输控制
滑动窗口(sliding window) 滑动窗口是用于流量控制的,发送端根据接收端的处理能力发送数据,不至于造成过多的丢包. 是发送方和接收方间的协调,对方的接收窗口大小就是自己的发送窗口大小. 在 ...
- C++虚函数表
大家知道虚函数是通过一张虚函数表来实现的.在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承.覆盖的问题,其内容真是反应实际的函数.这样,在有虚函数的类的实例中,这个表分配在了这个实例的内存中 ...
- Oracle VM VirtualBox配置文件
Linux 虚拟机配置文件分为两处. windows下: 1.用户名/.VirtualBox/ 这里面有2个配置文件: VirtualBox.xml 和 VirtualBox.xml-prev. 后面 ...
- yar粗略使用记录
yar是鸟哥(laruence)开发的一个并行的RPC框架.据说sina weibo已经在大规模使用这个框架了.今天初步使用了下,觉得还是挺爽的一个工具. 什么情况适用这个工具呢? 比如一般你有个微博 ...
- 我的Eclipse快捷键.
所谓“工欲善其事必先利其器”,程序写多了,对于快捷键总有些特别的偏爱.在众多编辑器中,Eclipse算是用的比较多,也是最熟的. 最常用(也是最爱的:)) Ctrl+’ : 自动完成提示.这个快捷键 ...
- Atititi 版本管理 rc final rtm ga release 软件的生命周期中一般分4个版本
Atititi 版本管理 rc final rtm ga release 软件的生命周期中一般分4个版本 RC=Release Candidate,含义是"发布候选版",它不是最终 ...
- salesforce 零基础学习(三十五) 通过Process Builder和Approval Processes锁定记录(Lock Record)
有的时候我们可能有这样的需求,当某个字段为特定的值情况下,便锁定此条记录,仅允许Profile为System Admin的用户修改或者解锁,其他的用户只能查看此条记录,不能修改此条记录,这种情况下我们 ...
- 【译】采用MVC模式创建一个简单的javascript App
原文标题:Build A Simple Javascript App The MVC Way 作者:joshcrawmer4 翻译人:huansky 初次翻译,翻译的不好,还请见谅 JavaScrip ...
- Markdown快速入门
现在博文写作次数渐渐变多,经常看到很多园友的博文样式都非常的美观,个人虽然是个土鳖,但对美也是有很强需求的,同时由于最近将要上线一个博客项目,因此也很关心如何可以更高效的编辑和发布博文.之前一直使用w ...
- BOM之window对象
双重角色 BOM的核心对象是window,它表示浏览器的一个实例.在浏览器中,window对象有双重角色,它既是通过Javascript访问浏览器窗口的一个接口,又是ECMAScript规定的Glob ...