一个排列组合算法---裂变算法

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方法中编写自己的对象比较代码。

posted @ 2009-01-15 20:52  andriod2012  阅读(579)  评论(0编辑  收藏  举报