组合序列、排列序列的生成实现
组合序列、排列序列的生成实现
前面我们已经讨论了关于组合数、排列数的生成《排列、组合的计算》,并没有涉及组合序列和排列序列是如何生成的。这里我们将讨论序列和排列序列是如何生成的,首先我们讨论组合序列。
一、组合序列
假如有如下集合(注意,集合中的元素是互异的):
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
我们从该集合中选取3个元素,问有多少种组合,这些组合具体是什么?
首先,我们给出程序如下:
// 组合序列的生成 #include <iostream> #include <vector> using namespace std; void comb(const vector<int>& arr, int beg, int m, vector<vector<int> >& coms, vector<int>& tmp, int& total) { if (m > arr.size() - beg) { return; } if (m == 0) { coms.push_back(tmp); ++total; } else { tmp.push_back(arr[beg]); comb(arr, beg+1, m-1, coms, tmp, total); tmp.pop_back(); comb(arr, beg+1, m, coms, tmp, total); } } int main() { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; vector<int> arr(a, a + sizeof (a) / sizeof (*a)); vector<vector<int> > coms; vector<int> tmp; int total = 0; comb(arr, 0, 4, coms, tmp, total); for (vector<vector<int> >::size_type i = 0; i != coms.size(); ++i) { for (vector<int>::size_type j = 0; j != coms[i].size(); ++j) { cout << coms[i][j] << ' '; } cout << endl; } cout << coms.size() << endl; cout << total << endl; system("PAUSE"); return 0; }
程序的算法是根据组合的特性而得的:C(N, M) = C(N-1, M-1) + C(N-1, M)。
程序运行的实例为:C(10, 4) = 210,组合数也可以根据之前的程序用公式得到。
二、排列序列
有集合:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
求该集合的排列。
根据排列的性质A(N, M) = N*A(N-1, M-1)。
我们利用这个性质用递归实现:
// 排列递归实现 #include <iostream> #include <vector> using namespace std; void exchange(int& a, int& b) { int t = a; a = b; b = t; } void perm( const vector<int>& arr_ , int n , int beg , vector<vector<int> >& pers , vector<int>& tmp , int& total ) { static vector<int> arr(arr_); if (n == 0) { pers.push_back(tmp); ++total; } for (int i = beg; i != arr.size(); ++i) { exchange(arr[beg], arr[i]); tmp.push_back(arr[beg]); perm(arr, n-1, beg+1, pers, tmp, total); tmp.pop_back(); exchange(arr[beg], arr[i]); } } int main() { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; vector<int> arr(a, a + sizeof (a) / sizeof (*a)); vector<bool> flags(arr.size(), false); vector<vector<int> > pers; vector<int> tmp; int total = 0; perm(arr, 3, 0, pers, tmp, total); for (vector<vector<int> >::size_type i = 0; i != pers.size(); ++i) { for (vector<int>::size_type j = 0; j != pers[i].size(); ++j) { cout << pers[i][j] << ' '; } cout << endl; } cout << pers.size() << endl; cout << total << endl; system("PAUSE"); return 0; }
程序的实现逻辑为:根据排列公式A(n, m) = n*A(n-1, m-1),对当前位置取n个元素,然后递归计算后面的A(n-1, m-1)。所以得到以上。
当arr为:
1, 2, 3, 4, 5, 6
时,求其全排列为:
三、总结
以上对组合序列和排列序列的生成程序进行了讨论。实质上就是根据组合的性质:
C(N, M) = C(N-1, M-1) + C(N-1, M)
以及排列的性质:
A(N, M) = N * A(N-1, M-1)
利用递归的方式进行求解。
由于组合公式中只是相加的方式,所以递归程序中不存在直接的循环。排列公式中存在变量N,所以在实际的实现种需要有直接的循环进行体现。
什么时候使用递归,如何使用递归,将在下一篇种进行介绍。
另外,关于组合、排列的程序实现,可以进行进一步的封装。我们这里没有进行进一步的封装。如果封装,有如下接口:
组合:void comb(const vector<int>& arr, int m, vector<vector<int> >& coms, int& total);
排列:void perm(const vector<int>& arr, int m, vector<vector<int> >& pers, int& total);
全排列:void full_perm(const vector<int>& arr, vector<vector<int> >& pers, int& total);
(完)
文档信息
·版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
·博客地址:http://www.cnblogs.com/unixfy
·博客作者:unixfy
·作者邮箱:goonyangxiaofang(AT)163.com
·如果你觉得本博文的内容对你有价值,欢迎对博主 小额赞助支持