组合的生成

点击下载[CSharp源代码之组合.rar]

 

 

  1 ExpandedBlockStart.gif ContractedBlock.gif /**/ /*
  2=========程序信息========
  3模块简介:组合生成类,从m个数中取出n个数进行组合,其中m > n(非递归生成)
  4版本号:1.0
  5使用语言:c#
  6使用编译器:Visual Studio 2005 .NET
  7每次生成组合所需时间:O(n)
  8作者:贵州大学05级 刘永辉 
  9昵称:SDJL
 10编写时间:2008年8月
 11联系QQ:44561907
 12E-Mail:44561907@qq.com
 13获得更多文章请访问我的博客:www.cnblogs.com/sdjl
 14如果发现BUG或有写得不好的地方请发邮件告诉我:)
 15==========算法介绍=======
 16我们先来看m=5、n=3的组合情况,如下:
 17 1 2 3
 18 1 2 4
 19 1 2 5
 20 1 3 4
 21 1 3 5
 22 1 4 5
 23 2 3 4
 24 2 3 5
 25 2 4 5
 26 3 4 5
 27仔细观察会发现下面的特性(这些特性对于m、n取任何值均成立):
 28 1、我们可以从前n个数开始进行组合
 29 2、每一次获得下一个组合时只要把最后一个数加1即可
 30 3、如果最后一个数达到了上界,即不能再增加时,则考虑增加前一个数,同样,如果前一个数也达到上界时,那么就增加前前一个数,依此类推
 31 4、不同的位置的数的上界不同,且从右向左依次减小,最后一个是n,第一个是 m-n+1
 32 5、当第i个数增加1且i不等于n时,需要改变第i个数右面的所有数的值,并且是从第i个数开始依次增加1
 33 6、当出现最大的n个数组成的组合后,所有的组合均已生成一遍
 34 */

 35
 36 using  System;
 37 using  System.Collections.Generic;
 38 using  System.Text;
 39
 40 namespace  SDJL.Combination
 41 ExpandedBlockStart.gifContractedBlock.gif {
 42ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
 43    /// 组合类[Write by SDJL]
 44    /// version:1.0
 45    /// </summary>

 46    public class Combination
 47ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 48ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 49        /// m个数的数组
 50        /// </summary>

 51        private object[] m_datas;
 52ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 53        /// 用于记录当前状态,
 54        /// </summary>
 55        /// <example>
 56        /// m_state[0]=3 表示生成的组合中第0个元素为所有元素中的第3个
 57        /// </example>

 58        private int[] m_state;
 59ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 60        /// 总元素个数
 61        /// </summary>

 62        private int m_m;
 63ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 64        /// 取出元素个数
 65        /// </summary>

 66        private int m_n;
 67ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 68        /// 是否还有下一个组合
 69        /// </summary>

 70        private bool m_hasNext = true;
 71        
 72ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 73        /// 是否还有下一个组合
 74        /// </summary>

 75        public bool HasNext
 76ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 77ExpandedSubBlockStart.gifContractedSubBlock.gif            get return m_hasNext; }
 78        }

 79
 80ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 81        /// 用数组构造组合
 82        /// O(m)
 83        /// </summary>
 84        /// <param name="datas">源数组</param>
 85        /// <param name="n">提取的元素个数</param>

 86        public Combination(object[] datas,int n) 
 87ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 88            m_datas = datas;
 89            m_n = n;
 90            m_m = datas.Length;
 91            m_state = new int[m_n];
 92            for (int i = 0; i < m_n; i++)
 93ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 94                m_state[i] = i;
 95            }

 96        }

 97
 98ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 99        /// 构造基于整数的组合
100        /// O(m)
101        /// </summary>
102        /// <param name="m">总共拥有的整数数</param>
103        /// <param name="n">提取元素个数</param>

104        public Combination(int m, int n)
105ExpandedSubBlockStart.gifContractedSubBlock.gif        {
106            m_n = n;
107            m_m = m;
108
109            m_datas = new object[m_m];
110            for (int i = 0; i < m_m; i++)
111ExpandedSubBlockStart.gifContractedSubBlock.gif            {
112                m_datas[i] = i;
113            }

114            
115            m_state = new int[m_n];
116            for (int i = 0; i < m_n; i++)
117ExpandedSubBlockStart.gifContractedSubBlock.gif            {
118                m_state[i] = i;
119            }

120        }

121
122ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
123        /// 获取下一个组合
124        /// O(n)
125        /// </summary>
126        /// <returns>当所有组合均获取完毕后返回null</returns>

127        public object[] Next()
128ExpandedSubBlockStart.gifContractedSubBlock.gif        {
129            object[] returnArray = null;
130            if (m_hasNext)
131ExpandedSubBlockStart.gifContractedSubBlock.gif            {
132                returnArray = MakeArray();
133                EnterNextState();
134            }

135            return returnArray;
136        }

137
138ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
139        /// 用状态[m_state]生成组合数组
140        /// O(n)
141        /// </summary>
142        /// <returns></returns>        

143        private object[] MakeArray()
144ExpandedSubBlockStart.gifContractedSubBlock.gif        {
145            object[] returnArray = new object[m_n];
146            for (int i = 0; i < m_n; i++)
147ExpandedSubBlockStart.gifContractedSubBlock.gif            {
148                returnArray[i] = m_datas[m_state[i]];
149            }

150
151            return returnArray;
152        }

153        
154ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
155        /// 进入下一个状态
156        /// O(n)
157        /// </summary>
158        /// <returns>
159        /// 当下一个状态存在时返回true,否则返回false
160        /// </returns>        

161        private bool EnterNextState()
162ExpandedSubBlockStart.gifContractedSubBlock.gif        {
163            //k是需要增加1的那个数,起初假设k是最后一个,注意程序中是从0开始编号
164            int k = m_n - 1;
165            //根据前面的分析,寻找到k的值
166            while ((k >= 0&& (m_state[k] + (m_n - k) == m_m))
167ExpandedSubBlockStart.gifContractedSubBlock.gif            {
168                k--;
169            }

170            //如果找到一个需要增加1的数
171            if (k>=0)
172ExpandedSubBlockStart.gifContractedSubBlock.gif            {
173                //如果这个数在最后的位置上
174                if (k==m_n-1)
175ExpandedSubBlockStart.gifContractedSubBlock.gif                {
176                    //给这个数增加1
177                    m_state[k]++;
178                }

179                else//否则这个数不在最后的位置上
180ExpandedSubBlockStart.gifContractedSubBlock.gif                {
181                    //给这个数增加1
182                    m_state[k]++;
183                    k++;
184                    //改变这个数后面的所有数的值,使得他们的值依次增加1
185                    while (k<m_n)
186ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
187                        m_state[k] = m_state[k - 1+ 1;
188                        k++;
189                    }

190                }

191                m_hasNext = true;
192            }

193            else//否则找不到需要增加1的数
194ExpandedSubBlockStart.gifContractedSubBlock.gif            {
195                //已经不能再次生成组合了
196                m_hasNext = false;
197            }

198            return m_hasNext;
199        }

200    }

201}

202

转载于:https://www.cnblogs.com/SDJL/archive/2008/08/18/1270546.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值