C#排序算法——二路归并法
2008-09-08 22:07
323 查看
在阅读此博文前,请先阅读我的博文“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);
}
}
}
另一种二路归并排序算法是这样的:首先将每两个相邻的大小为1的子序列归并,然后对
上一次归并所得到的大小为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];
}
}
}
}
“,以了解基类的结构。
在编写代码前,我们先来了解二路归并法的排序过程:
假设有一个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);
}
}
}
另一种二路归并排序算法是这样的:首先将每两个相邻的大小为1的子序列归并,然后对
上一次归并所得到的大小为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];
}
}
}
}