排列组合n选m C++实现
2016-05-22 15:31
323 查看
排列组合n选m算法
本代码实现http://blog.chinaunix.net/uid-20684578-id-1572099.html所介绍找10组合算法。算法摘要:
本程序的思路是开一个n长度的数组,其下标表示为0到n-1,数组元素的值为1表示其下标代表的数被选中,为0则没选中,算法过程:
1)初始化,将数组前m个元素置1,表示第一个组合为前m个数
2)然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端
3)重复1), 2)步骤,直到无法找到”10”组合
注:n选m组合数量为
n!(n−m)!∗m!
例如求5中选3的组合:
1 1 1 0 0 //1,2,3 1 1 0 1 0 //1,2,4 1 0 1 1 0 //1,3,4 0 1 1 1 0 //2,3,4 1 1 0 0 1 //1,2,5 1 0 1 0 1 //1,3,5 0 1 1 0 1 //2,3,5 1 0 0 1 1 //1,4,5 0 1 0 1 1 //2,4,5 0 0 1 1 1 //3,4,5
-实现代码
#include <stdlib.h> #include <stdio.h> #include <memory.h> #include <vector> using namespace std; #define FLAG_1 1 #define FLAG_0 0 #define POS_NULL -1 void GetSelectedItems(char *flags, int flagCnt, vector<vector<int> > &vvCombin) { if (NULL == flags) return; vector<int> vecItems; for (int i = 0; i < flagCnt; ++i) { if (flags[i] != FLAG_0) vecItems.push_back(i); } vvCombin.push_back(vecItems); } int Find10Pos(char *flags, int flagCnt) { for (int i = 1; i < flagCnt; ++i) { if (flags[i - 1] == FLAG_1 && flags[i] == FLAG_0) { return i - 1; } } return -1; } void Swap10Pos(char *flags, int pos) { //10->01 flags[pos + 0] = FLAG_0; flags[pos + 1] = FLAG_1; } void ShiftToLeft(char *flags, int endPos) { int cnt = 0; for (int i = 0; i < endPos; ++i) { if (flags[i] == FLAG_1) { ++cnt; flags[i] = FLAG_0; } } for (int i = 0; i < cnt; ++i) { flags[i] = FLAG_1; } } bool Select(int n, int m, vector<vector<int> > &vvOut) { if (m > n) return false; vvOut.clear(); char *flags = new char ; if (NULL == flags) return false; memset(flags, false, n); for (int i = 0; i < m; ++i) { flags[i] = true; } GetSelectedItems(flags, n, vvOut); int pos = Find10Pos(flags, n); while (pos != POS_NULL) { Swap10Pos(flags, pos); ShiftToLeft(flags, pos); GetSelectedItems(flags, n, vvOut); pos = Find10Pos(flags, n); } delete[]flags; return true; } void main() { vector<vector<int> > vvCombin; Select(10, 3, vvCombin); int nTotalCnt = 0; for (size_t i = 0; i < vvCombin.size(); ++i) { vector<int> &vecItems = vvCombin[i]; for (size_t j = 0; j < vecItems.size(); j++) { printf_s("%d\t", vecItems[j] + 1); } printf_s("\n"); ++nTotalCnt; } printf_s("Total count:%d\n", nTotalCnt); }
相关文章推荐
- c++ primer(第五版)学习笔记及习题答案代码版(第九章)顺序容器
- C++面向对象编程分享11----系统设计01
- c++作业6
- 关于求一个数的阶乘的C语言
- c++ 中__declspec 的用法
- ubuntu下安装eclipse(c++)
- C语言知识点总结
- C语言 抽象数据类型ADT
- c++作业六
- 浅谈C语言中结构体的初始化
- 通过引用计数实现智能指针(C++ Primer)
- C++课堂作业(2)
- C++课堂作业(2)
- c++实验6——数组合并
- Ubuntu 14 g++ 使用c++11特性报错
- 单链表及其基本操作(C语言实现)
- C语言基本数据类型大小
- C++ 高级篇(二)—— 名空间 (Namespaces)
- C++ 高级篇(一)—— 模板(Templates)
- 问题:c++中0,‘\0’,‘0’,"0"有什么区别