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
12
E-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

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202
