您的位置:首页 > 编程语言 > C#

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];

}

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: