全排列、子集
来源:互联网 发布:淘宝网韩版女装秋季 编辑:程序博客网 时间:2024/05/21 17:30
问题
输出数组P[a,b,b,b]的全排列\全子集 ; 注意集合元素有重复
测试
#define N 4char P[]={'a', 'b', 'b', 'c'}int main(){ int i, j, A[N]; printf("全排列-递归\n"); permutation1(N, A, 0); printf("全排列-非递归\n"); //用索引 转化数组P 为A[1, 2, 2, 4] for(i=0; i<N; i++) { if( i==0 || P[i]!=P[i-1] ) j = i; A[i]=j; } permutation2(N, P); printf("子集--增量构造--没有去重\n"); subset1(N, A, 0); printf("子集--位向量--没有去重\n"); subset2(N, A, 0); printf("子集--二进制--去重啦\n"); //用索引 转化数组P 为A[1, 2, 2, 4] for(i=0; i<N; i++) { if( i==0 || P[i]!=P[i-1] ) j = i; A[i]=j; } memset(HashArray, -1, sizeof(HashArray)); subset3(N, A);}输出:全排列-递归a b b b b a b b b b a b b b b a 全排列-非递归a b b b b a b b b b a b b b b a 子集--增量构造--没有去重a a b a b b a b b b a b b a b a b b a b b b b b b b b b b b b b 子集--位向量--没有去重b b b b b b b b b b b b a a b a b a b b a b a b b a b b a b b b 子集--二进制--去重啦a b a b b b a b b b b b a b b b
全排列
递归算法
/* 递归 * 不断的填充索引A[cur]的值 直到cur==n */void permutation1(int n, int *A, int cur){ int i,j,c1,c2; if(cur==n) { for(i=0; i<n; i++) { printf("%c ", P[A[i]]); } printf("\n"); return; } for(i=0;i<n;i++) if( i==0 || P[i]!=P[i-1] ) { c1=c2=0; for(j=0;j<cur;j++) if(P[i]==P[A[j]]) c1++; // 已经出现次数 for(j=0;j<n && c1>=c2; j++) if(P[i]==P[j]) c2++; // 是否至少出现了c1+1次 if( c1 < c2 ) { A[cur]=i; permutation1(n, A, cur+1); } }}
非递归算法
/* 非递归 */void permutation2(int n, int *A){ int i, j; /* * 从字典序最小[升序排列] 逐步增大 直到 字典序最大[降序排列] * 算法: * 初始态 值升序排列 * 从右往左找到i 使得 A[i] > A[i+1] && A[i+1:]降序 < i==-1 A[0:] 已经是降序排列了 算法结束 > * 从右往左找到j 使得 A[i] < A[j]; * 逆序 A[i+1:] */ while(1) { //打印 for(i=0; i<n; i++) printf("%c ", P[A[i]]); printf("\n"); //find 临界点A[i] i=n-2; while( i>=0 && A[i]>=A[i+1]) i--; if(i==-1) return; //find 比A[i]大的数字A[j] j=n-1; while(A[i]>=A[j]) j--; // exchange A[i] ^= A[j]; A[j] ^= A[i]; A[i] ^= A[j]; // reversed A[i+1:] for(i=i+1, j=n-1; i<j; i++,j--) { A[i] ^= A[j]; A[j] ^= A[i]; A[i] ^= A[j]; } }}
子集
子集–增量构造
/* 子集--增量构造发 */void subset1(int n, int *A, int cur ){ int i, s; for(i=0; i<cur; i++) printf("%c ", P[A[i]]); printf("\n"); s = cur ? A[cur-1]+1 : 0; for(i=s; i<n; i++) { A[cur]=i; subset1(n, A, cur+1); }}
子集–位向量
void subset2(int n, int *A, int cur){ int i; if(cur==n) { for(i=0; i<n; i++) if(A[i]) printf("%c ", P[i]); printf("\n"); return; } A[cur]=0; subset2(n, A, cur+1); A[cur]=1; subset2(n, A, cur+1);}
子集–二进制
/* 判断n是否出现过 需要初始化memset(HashArray, -1, sizeof(HashArray)) * HashArray大小应该要大于所有无重复子集的个数 * */static int HashArray[1024];int hasExisted(int n){ int LEN=1024; int k = n%LEN; while( HashArray[k]!=-1 && HashArray[k]!=n && k!=(n%LEN-1)%LEN) k=(k+1)%LEN; if (k==(n%LEN-1)%LEN){ return 2; // 数据满了 } if (HashArray[k]==-1) // 没有n { HashArray[k]=n; return 0; } return 1;}/*子集--二进制*/void subset3(int n, int *A){ int i=0, j=0, code; while(i < 1<<n) { code=1; for(j=0; j<n ; j++) if( i & 1<<j ) code = code*10+A[j]; switch( hasExisted(code) ) { case 1: break; case 2: printf("数据error!\n"); return; case 0: for(j=0; j<n ; j++) if( i & 1<<j ) printf("%c ", P[A[j]]); printf("\n"); break; } i++; }}
阅读全文
0 0
- 全排列、子集
- 全排列与子集生成
- 子集和全排列问题
- 【java】全排列 枚举子集
- 子集生成+stl全排列
- 求集合的子集、全排列总结
- 求数组的全部子集 && 全排列
- 子集(全排列的延伸)
- 回溯法 求集合全排列、子集
- 全排列以及集合的子集
- 算法--全排列、全子集、DFS\BFS问题
- 代码--C++全排列和子集的实现
- 总结帖:全排列Permutation,子集subset 递归模板
- 算法 全排列问题,组合问题,子集问题
- 【C语言】递归实现元素的全排列和子集
- 字符串(集合)的全排列和子集
- 非重复生成全子集组合排列(含重复数字时,生成不重复全子集组合排列)
- 求集合子集,和全排列的递归算法实现(c++,Dev C++调试通过)
- linux安装配置zookeeper-3.4.10
- Unity3D 5.x 启动过程中 License Error 解决办法
- C++ 单链表操作
- JDBC详细总结
- C语言 if条件判断中包含语句块
- 全排列、子集
- js中Event 对象 target 与 currentTarget的应用
- 【ZJOI2016&&BZOJ4574】【NOIP模拟】作弊(DP&&随机数据)
- 第二章 Java内存区域与内存溢出异常
- 网易疯狂队列
- 2.计算机组成原理笔记二发展应用及相关知识
- 自然语言学习心得2
- C++基础之指针作为函数的参数
- Centos7.x