1
/**/
/*
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 {
42 /**//// <summary>
43 /// 组合类[Write by SDJL]
44 /// version:1.0
45 /// </summary>
46 public class Combination
47 {
48 /**//// <summary>
49 /// m个数的数组
50 /// </summary>
51 private object[] m_datas;
52 /**//// <summary>
53 /// 用于记录当前状态,
54 /// </summary>
55 /// <example>
56 /// m_state[0]=3 表示生成的组合中第0个元素为所有元素中的第3个
57 /// </example>
58 private int[] m_state;
59 /**//// <summary>
60 /// 总元素个数
61 /// </summary>
62 private int m_m;
63 /**//// <summary>
64 /// 取出元素个数
65 /// </summary>
66 private int m_n;
67 /**//// <summary>
68 /// 是否还有下一个组合
69 /// </summary>
70 private bool m_hasNext = true;
71
72 /**//// <summary>
73 /// 是否还有下一个组合
74 /// </summary>
75 public bool HasNext
76 {
77 get { return m_hasNext; }
78 }
79
80 /**//// <summary>
81 /// 用数组构造组合
82 /// O(m)
83 /// </summary>
84 /// <param name="datas">源数组</param>
85 /// <param name="n">提取的元素个数</param>
86 public Combination(object[] datas,int n)
87 {
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++)
93 {
94 m_state[i] = i;
95 }
96 }
97
98 /**//// <summary>
99 /// 构造基于整数的组合
100 /// O(m)
101 /// </summary>
102 /// <param name="m">总共拥有的整数数</param>
103 /// <param name="n">提取元素个数</param>
104 public Combination(int m, int n)
105 {
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++)
111 {
112 m_datas[i] = i;
113 }
114
115 m_state = new int[m_n];
116 for (int i = 0; i < m_n; i++)
117 {
118 m_state[i] = i;
119 }
120 }
121
122 /**//// <summary>
123 /// 获取下一个组合
124 /// O(n)
125 /// </summary>
126 /// <returns>当所有组合均获取完毕后返回null</returns>
127 public object[] Next()
128 {
129 object[] returnArray = null;
130 if (m_hasNext)
131 {
132 returnArray = MakeArray();
133 EnterNextState();
134 }
135 return returnArray;
136 }
137
138 /**//// <summary>
139 /// 用状态[m_state]生成组合数组
140 /// O(n)
141 /// </summary>
142 /// <returns></returns>
143 private object[] MakeArray()
144 {
145 object[] returnArray = new object[m_n];
146 for (int i = 0; i < m_n; i++)
147 {
148 returnArray[i] = m_datas[m_state[i]];
149 }
150
151 return returnArray;
152 }
153
154 /**//// <summary>
155 /// 进入下一个状态
156 /// O(n)
157 /// </summary>
158 /// <returns>
159 /// 当下一个状态存在时返回true,否则返回false
160 /// </returns>
161 private bool EnterNextState()
162 {
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))
167 {
168 k--;
169 }
170 //如果找到一个需要增加1的数
171 if (k>=0)
172 {
173 //如果这个数在最后的位置上
174 if (k==m_n-1)
175 {
176 //给这个数增加1
177 m_state[k]++;
178 }
179 else//否则这个数不在最后的位置上
180 {
181 //给这个数增加1
182 m_state[k]++;
183 k++;
184 //改变这个数后面的所有数的值,使得他们的值依次增加1
185 while (k<m_n)
186 {
187 m_state[k] = m_state[k - 1] + 1;
188 k++;
189 }
190 }
191 m_hasNext = true;
192 }
193 else//否则找不到需要增加1的数
194 {
195 //已经不能再次生成组合了
196 m_hasNext = false;
197 }
198 return m_hasNext;
199 }
200 }
201}
202
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 {
42 /**//// <summary>
43 /// 组合类[Write by SDJL]
44 /// version:1.0
45 /// </summary>
46 public class Combination
47 {
48 /**//// <summary>
49 /// m个数的数组
50 /// </summary>
51 private object[] m_datas;
52 /**//// <summary>
53 /// 用于记录当前状态,
54 /// </summary>
55 /// <example>
56 /// m_state[0]=3 表示生成的组合中第0个元素为所有元素中的第3个
57 /// </example>
58 private int[] m_state;
59 /**//// <summary>
60 /// 总元素个数
61 /// </summary>
62 private int m_m;
63 /**//// <summary>
64 /// 取出元素个数
65 /// </summary>
66 private int m_n;
67 /**//// <summary>
68 /// 是否还有下一个组合
69 /// </summary>
70 private bool m_hasNext = true;
71
72 /**//// <summary>
73 /// 是否还有下一个组合
74 /// </summary>
75 public bool HasNext
76 {
77 get { return m_hasNext; }
78 }
79
80 /**//// <summary>
81 /// 用数组构造组合
82 /// O(m)
83 /// </summary>
84 /// <param name="datas">源数组</param>
85 /// <param name="n">提取的元素个数</param>
86 public Combination(object[] datas,int n)
87 {
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++)
93 {
94 m_state[i] = i;
95 }
96 }
97
98 /**//// <summary>
99 /// 构造基于整数的组合
100 /// O(m)
101 /// </summary>
102 /// <param name="m">总共拥有的整数数</param>
103 /// <param name="n">提取元素个数</param>
104 public Combination(int m, int n)
105 {
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++)
111 {
112 m_datas[i] = i;
113 }
114
115 m_state = new int[m_n];
116 for (int i = 0; i < m_n; i++)
117 {
118 m_state[i] = i;
119 }
120 }
121
122 /**//// <summary>
123 /// 获取下一个组合
124 /// O(n)
125 /// </summary>
126 /// <returns>当所有组合均获取完毕后返回null</returns>
127 public object[] Next()
128 {
129 object[] returnArray = null;
130 if (m_hasNext)
131 {
132 returnArray = MakeArray();
133 EnterNextState();
134 }
135 return returnArray;
136 }
137
138 /**//// <summary>
139 /// 用状态[m_state]生成组合数组
140 /// O(n)
141 /// </summary>
142 /// <returns></returns>
143 private object[] MakeArray()
144 {
145 object[] returnArray = new object[m_n];
146 for (int i = 0; i < m_n; i++)
147 {
148 returnArray[i] = m_datas[m_state[i]];
149 }
150
151 return returnArray;
152 }
153
154 /**//// <summary>
155 /// 进入下一个状态
156 /// O(n)
157 /// </summary>
158 /// <returns>
159 /// 当下一个状态存在时返回true,否则返回false
160 /// </returns>
161 private bool EnterNextState()
162 {
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))
167 {
168 k--;
169 }
170 //如果找到一个需要增加1的数
171 if (k>=0)
172 {
173 //如果这个数在最后的位置上
174 if (k==m_n-1)
175 {
176 //给这个数增加1
177 m_state[k]++;
178 }
179 else//否则这个数不在最后的位置上
180 {
181 //给这个数增加1
182 m_state[k]++;
183 k++;
184 //改变这个数后面的所有数的值,使得他们的值依次增加1
185 while (k<m_n)
186 {
187 m_state[k] = m_state[k - 1] + 1;
188 k++;
189 }
190 }
191 m_hasNext = true;
192 }
193 else//否则找不到需要增加1的数
194 {
195 //已经不能再次生成组合了
196 m_hasNext = false;
197 }
198 return m_hasNext;
199 }
200 }
201}
202