开发工具:
Visual Studio v2010
.NET Framework 4 Client Profile
版本历史:
V1.0 2011年06月22日
- 通过递归和非递归算法实现按顺序输出的全排列。
参考资料:
下载地址:
源代码:
FullPermutation.cs
/* ----------------------------------------------------------
文件名称:FullPermutation.cs
作者:秦建辉
MSN:splashcn@msn.com
QQ:36748897
版本历史:
V1.0 2011年06月22日
递归和非递归算法实现的全排列类库
参考资料:
http://plutoblog.iteye.com/blog/976216
http://tieba.baidu.com/f?kz=12248706
------------------------------------------------------------ */
using System;
using System.Collections.Generic;
namespace Splash
{
/// <summary>
/// 递归和非递归实现按顺序输出的全排列类库
/// </summary>
public static class FullPermutation
{
/// <summary>
/// 递归实现的按顺序输出的全排列数组列表
/// </summary>
/// <param name="index">起始索引号</param>
/// <param name="length">元素个数</param>
/// <returns>全排列数组列表</returns>
public static List<Int32[]> Seed(Int32 index, Int32 length)
{
if (length <= 0) return null;
Int32[] used = new Int32[length];
Int32[] result = new Int32[length];
List<Int32[]> list = new List<Int32[]>();
Array.Clear(used, 0, length); // 初始化
Proc(0, index, length, list, used, result);
return list;
}
// 递归实现
private static void Proc(Int32 step, Int32 index, Int32 length, List<Int32[]> list, Int32[] used, Int32[] result)
{
if (step == length)
{
list.Add((Int32[])result.Clone()); // 注意:克隆数组
}
else
{
for (Int32 i = 0; i < length; i++)
{
if (used[i] == 0)
{
used[i] = 1;
result[step] = index + i;
Proc(step + 1, index, length, list, used, result);
used[i] = 0;
}
}
}
}
/// <summary>
/// 非递归实现的按顺序输出的全排列迭代器
/// </summary>
/// <param name="index">起始索引号</param>
/// <param name="length">元素个数</param>
/// <returns>全排列迭代器</returns>
/// <remarks>
/// 基本思想:
/// 1. 找到所有排列中最小的一个排列P
/// 2. 找到刚刚好比P大比其它都小的排列Q
/// 3. 循环执行第二步,直到找到一个最大的排列,算法结束
/// </remarks>
public static System.Collections.IEnumerable Cell(Int32 index, Int32 length)
{
if (length <= 0)
{ // 迭代结束
yield break;
}
else if (length == 1)
{ // 只有一个元素
yield return new Int32[] { index };
}
else
{ // 生成一个最小排列
Int32[] A = new Int32[length];
for (Int32 i = 0; i < length; i++)
A[i] = index + i;
while (true)
{
yield return A;
Int32 i, j;
// 从后向前找出不符合从大到小的元素A[i]
for (i = length - 2; i >= 0; i--)
{
if (A[i] < A[i + 1])
break;
else if(i == 0)
yield break; // 所有元素都满足从大到小,迭代结束
}
// 从后向前找出比其大的元素A[j]
for (j = length - 1; j > i; j--)
{
if (A[j] > A[i]) break;
}
// 交换A[i]和A[j]
A[i] ^= A[j];
A[j] ^= A[i];
A[i] ^= A[j];
// 反转后面的元素,使A[i]后面的元素变成最小排列
Array.Reverse(A, i + 1, length - i - 1);
}
}
}
}
}