在阅读此博文前,请先阅读我的博文“C#排序算法——基类设计 “,以了解基类的结构。
在编写代码前,我们先来了解二路归并法的排序过程:
假设有一个IList<T>型的集合list(集合的元素为list[0]到list[n-1], n = list.Count)。
第1步:将list平均分为两个子集:左子集list[0]:list[middle]和右子集list[middle + 1]:list[n - 1](middle = n / 2)。
第2步:分别对左子集和右子集用二路归并法进行排序。
第3步,将排序后的左子集和右子集合并,构造出有序集合list.
很显然,二路归并法使用了递归调用。根据上面的算法,我们开始编码了:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace CYB.DataStruct.Sorting
- {
- /// <summary>
- /// 作者 : cyb
- /// 发表时间 : 2008-9-8
- /// qq : 13101908
- /// e-mail : hustcyb@gmail.com
- /// </summary>
- public class MergeSorter : Sorter
- {
- public override void Sort<T>(IList<T> list, CompareDelegate<T> compare)
- {
- base .Sort(list, compare);
- this .Sort(list, 0, list.Count - 1, compare);
- }
- private void Merge<T>(IList<T> list, int start, int middle, int end, CompareDelegate<T> compare)
- {
- T[] array = new T[end - start + 1]; //存储集合元素的临时数组
- int index = 0; //指示arry中位置的游标
- int left = start; //指示左子集位置的游标
- int right = middle + 1; //指示右子集位置的游标
- while (left <= middle && right <= end)
- {
- if (compare(list[left], list[right]) < 0)
- {
- array[index++] = list[left++];
- }
- else
- {
- array[index++] = list[right++];
- }
- }
- //将左子集中剩余元素复制到临时数组中(如果还有的话)
- while (left <= middle)
- {
- array[index++] = list[left++];
- }
- //将右子集中剩余元素复制到临时数组中(如果还有的话)
- while (right <= end)
- {
- array[index++] = list[right++];
- }
- //将有序的临时数组复制到集合中
- for (index = 0; index < array.Length; index++)
- {
- list[start + index] = array[index];
- }
- }
- private void Sort<T>(IList<T> list, int start, int end, CompareDelegate<T> compare)
- {
- if (start >= end)
- {
- return ; //当集合中的元素少于1个,不作处理
- }
- //分割集合
- int middle = (start + end) / 2;
- Sort(list, start, middle, compare); //使用二路归并法对左子集排序
- Sort(list, middle + 1, end, compare); //使用二路归并法对右子集排序
- //合并子集
- Merge(list, start, middle, end, compare);
- }
- }
- }
上一次归并所得到的大小为2的子序列进行相邻归并,如此反复,直至最后归并到一个序列,
归并过程完成:
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace CYB.DataStruct.Sorting
- {
- /// <summary>
- /// 作者 : cyb
- /// 发表时间 : 2008-9-8
- /// qq : 13101908
- /// e-mail : hustcyb@gmail.com
- /// </summary>
- public class MergeSorter : Sorter
- {
- public override void Sort<T>(IList<T> list, CompareDelegate<T> compare)
- {
- base .Sort(list, compare);
- Sort(list, 1, compare);
- }
- private void Sort<T>(IList<T> list, int interval, CompareDelegate<T> compare)
- {
- if (interval >= list.Count)
- {
- return ;
- }
- for ( int middle = interval - 1; middle < list.Count; middle += 2 * interval)
- {
- int start = middle - (interval - 1);
- int end = middle + interval;
- if (end >= list.Count)
- {
- end = list.Count - 1;
- }
- Merge(list, start, middle, end, compare);
- }
- Sort(list, 2 * interval, compare);
- }
- private void Merge<T>(IList<T> list, int start, int middle, int end, CompareDelegate<T> compare)
- {
- T[] array = new T[end - start + 1]; //存储集合元素的临时数组
- int index = 0; //指示arry中位置的游标
- int left = start; //指示左子集位置的游标
- int right = middle + 1; //指示右子集位置的游标
- while (left <= middle && right <= end)
- {
- if (compare(list[left], list[right]) < 0)
- {
- array[index++] = list[left++];
- }
- else
- {
- array[index++] = list[right++];
- }
- }
- //将左子集中剩余元素复制到临时数组中(如果还有的话)
- while (left <= middle)
- {
- array[index++] = list[left++];
- }
- //将右子集中剩余元素复制到临时数组中(如果还有的话)
- while (right <= end)
- {
- array[index++] = list[right++];
- }
- //将有序的临时数组复制到集合中
- for (index = 0; index < array.Length; index++)
- {
- list[start + index] = array[index];
- }
- }
- }
- }