一个排列组合算法---裂变算法
2009年1月15日 沈阳 晴
为解决1月7日遇到的排列组合的难题,进行了以下题目的研究,并用C#实现了一个非递归的算法。
有一个List,List中存有N个对象,要求做出这N个对象所有无序组。
数学公式:组合数=C(n,1) + C(n,2) + ...... + C(n,n)
C#的算法实现:
一.组合生成器:
using System;
using System.Collections.Generic;
using System.Text;
namespace CollectionApp
{
public class CombinationMaker<T>
{
//T类型元素组合表
public Dictionary<string, List<T>> CombinationTable;
public CombinationMaker()
{
//
}
//在组合表中添加新元素
public void addElement(T ce)
{
try
{
//元素组合表是空的场合
if (CombinationTable == null)
{
CombinationTable = new Dictionary<string, List<T>>();
}
//做成临时组合表
Dictionary<string, List<T>> newCombinationTable = new Dictionary<string, List<T>>();
//添加元素本身
List<T> selfLst = new List<T>();
selfLst.Add(ce);
newCombinationTable.Add(ce.ToString(), selfLst);
//新的组合列表
List<T> newCombLst = null;
foreach (string key in CombinationTable.Keys)
{
List<T> lst = CombinationTable[key];
//做成新的组合类型
newCombLst = this.makeNewCombination(ce, lst);
if (newCombLst != null)
{
//把新的组合类型添加到临时组合表中。
string key1 = "";
foreach (T ele in newCombLst)
{
key1 = key1 + "-" + ele.ToString();
}
newCombinationTable.Add(key1, newCombLst);
}
}
//把临时组合表中组合类型添加到类的组合表的成员属性中
foreach (string key in newCombinationTable.Keys)
{
CombinationTable.Add(key, newCombinationTable[key]);
}
}
catch (Exception ex)
{
throw new Exception("", ex);
}
}
//做成新的组合类型
private List<T> makeNewCombination(T ce, List<T> lst)
{
List<T> newCombLst = null;
try
{
bool flag = true;
//检索原有组合中是否存在元素ce
foreach (T element in lst)
{
if (element.Equals(ce) == true)
{
flag = false;
break;
}
}
//在原有组合中,元素ce不存在的场合,做成新的组合
if (flag == true)
{
T[] copyArr = new T[lst.Count];
lst.CopyTo(copyArr);
newCombLst = new List<T>();
newCombLst.AddRange(copyArr);
newCombLst.Add(ce);
}
}
catch (Exception ex)
{
throw new Exception("", ex);
}
//返回新的组合
return newCombLst;
}
}
}
二.测试程序
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace CollectionApp
{
class Program
{
static void Main(string[] args)
{
CombinationMaker<int> cm = new CombinationMaker<int>();
List<int> elementLst = new List<int>();
elementLst.Add(1);
elementLst.Add(2);
elementLst.Add(3);
elementLst.Add(4);
foreach (int item in elementLst)
{
cm.addElement(item);
}
foreach (string key in cm.CombinationTable.Keys)
{
System.Console.WriteLine("组合:" + key);
foreach (int element in cm.CombinationTable[key])
{
System.Console.WriteLine(" 组合元素:" + element);
}
}
}
}
}
三.算法小结
1.没有使用传统的递归算法,组合生成器的算法简单易懂,且容易调试;
2.组合生成器使用泛型技术,能够满足不同类型的数据对象要求;
3.组合生成器的对象比较时,使用对象的Equals方法,对于C#的基本数据类型,能够完全满足要求,但是对于复杂的数据对象,需要重载其Equals方法,在重载的Equals方法中编写自己的对象比较代码。