user-0 提问: 向大神求助C语言从ABCDEFHIJK选出8个的所有排列输出

回复:
user: user-1
content: http://en.cppreference.com/w/cpp/algorithm/next_permutation 这个可以作为参考。

user: user-2
content: #include <stdio.h> #include <stdlib.h>  void   perm(char array[], int n, int m);  int main(void) {     char   array[10] = {'A', 'B', 'C', 'D', 'E', 'F', 'H', 'I', 'J', 'K'};      perm(array, 5, 3);     return 0; /*************************************** 输出结果： ABC ACB BAC BCA CAB CBA ABD ADB BAD BDA DAB DBA ABE AEB BAE BEA EAB EBA ACD ADC CAD CDA DAC DCA ACE AEC CAE CEA EAC ECA ADE AED DAE DEA EAD EDA BCD BDC CBD CDB DBC DCB BCE BEC CBE CEB EBC ECB BDE BED DBE DEB EBD EDB CDE CED DCE DEC ECD EDC ***************************************/ }   /* 排列 */ /* 打印从n个数中选择m个数的排列 */ /* 当m = n时所有的排列情况叫全排列 */ /* 先用二进制转化法，模拟手动按顺序枚举所有组合，再将每个组合按字典顺序换位，得到排列。 */ /*****************************************************************  * A B C D  （4个字母排列）  * -----------------  * 0 1 2 3   A B C D     * 0 1 3 2   A B D C  （将右边第1个比右边数字小的数【这里是1】和其右边所有比它大的数中最小的数【这里是2】交换，   * 0 2 1 3   A C B D    变成0231，再将2后面的所有数反序，变成0213）   * 0 2 3 1   A C D B  * 0 3 1 2   A D B C  * 0 3 2 1   A D C B  * 1 0 2 3   B A C D  * 1 0 3 2   B A D C  * 1 2 0 3   B C A D   *   * ...  *  *****************************************************************/ void perm(char array[], int n, int m) {     int    i, j, k, flag, cnt, tmp;     int    *buf, *arr;      buf = (int*) calloc(n, sizeof(int));     arr = (int*) calloc(m, sizeof(int));      /* 初始化 */     for (i = 0; i < m; i++)         buf[i] = 1;      while (1) {     	/* 得到一个组合 */         for (i = 0, j = 0; i < n; i++) {             if (buf[i])                 arr[j++] = i;         }         /* 将每个组合按字典顺序换位，得到排列 */         while (1) {             for (i = 0; i < m; i++)                 printf("%c", array[arr[i]]);             printf(" ");              /* 找到右边第1个比右边数字小的数P(i) */             for (i = m - 1 - 1; i >= 0; i--)                 if (arr[i] < arr[i + 1])                     break;             if (i == -1) break;              /* 找到P(i)之后比P(i)大的最小的数P(k) */             for (j = i + 1, k = j; j < m; j++)                 if (arr[j] > arr[i] && arr[j] < arr[k])                     k = j;              /* 交换P(i)和P(k) */             tmp = arr[i];             arr[i] = arr[k];             arr[k] = tmp;              /* 将P(i)之后的数反序 */             for (j = i + 1, i = m - 1; j < i; j++, i--) {                 tmp = arr[j];                 arr[j] = arr[i];                 arr[i] = tmp;             }         }         printf("\n");          /* 检查是否已经列出所有的组合，如果后m位都为1，说明已列出所有组合 */         flag = 1;         for (i = n - m; i < n; i++) {             if (buf[i] == 0) {                 flag = 0;                 break;             }         }         if (flag) break;          /* 将右边第1个“10”组合变成“01” */         for (i = n - 1; i > 0; i--) {             if (buf[i] == 0 && buf[i - 1] == 1) {                 buf[i] = 1;                 buf[i - 1] = 0;                 break;             }         }          /* 如果最后一位为1，则将右端所有连续的1移动到第i（最后一个“10”）位之后，其它位设为0 */         if (buf[n - 1]) {             for (j = n - 1, cnt = 0; j > i; j--) {                 if (buf[j] == 0)                     break;                 cnt++;             }             for (j = i + 1; j < n; j++) {                 if (j < i + 1 + cnt)                     buf[j] = 1;                 else                     buf[j] = 0;             }         }     } }

user: user-2
content: 你确定是从ABCDEFHIJK里面选，不是ABCDEFGHIJ？ 试了一下，10个里面选8个，输出到.txt，文件有15.5MB  下面上个少点的，5个里面选3个

user: user-3
content: 引用 3 楼 u011260902 的回复:[quote=引用 2 楼 uuuououlcz 的回复:] P(8,10) = 1814400，百万级别的复杂度了呢，这么大的东西还是建议打印到文件里方便观察，不过这样文件的大小就是1814400 * 10(文本模式打开，加上\r\n的换行) = 18144000B = 18.144MB字节了，有点大了呢，加上递归的消耗目测要是10秒的数量级了哦 嗯嗯 谢谢，不知道这样程序的代码该怎么入手呢？有没什么建议。[/quote]  如果是我的话，就将问题分成两块： 1、是从10个字符的字符串里选出8个字负，这样的取法一共有C(8,10) = C(2,10) = 10*9/2 = 45个； 2、是将1中选出的8个字符进行全排列 全排的代码很常见，这里就不多说了，下面给出一个10个字符里选8个的方法，肯定还有更好的方法，所以仅供参考： /*   从N个字符的字符数组src中选取M个，将这样的组合形成的string放入vector<string>中   例如： int main() {     vector<string> v;     string s;      getCombination(v, s, 0, "ABCDEFHIJK", 10, 8);     cout<<v.size()<<endl;     for(int i = 0; i < v.size(); ++i) cout<<v[i]<<endl;     return 0; } */ void getCombination(vector<string>& v, string& help, int index, const char* src, const int N, const int M) {     //already choose M from N     if(help.size() == M){         v.push_back(help);         return;     }     //check if the rest is enough to fill the gap     if(N - index == M - help.size()){         int size = help.size();         for(index; index < N; ++index) help.push_back(src[index]);         v.push_back(help);         help.erase(size);         return;     }     /*       If it goes here, then the characters left is more than we need to make a M length string.       So for src[index], we have two options, one is to chose it, while the other is not.     */     int size = help.size();     help.push_back(src[index]);                     //here goes the first option, choose     getCombination(v, help, index+1, src, N, M);    //continue the first option     help.erase(size);                               //here goes the second option, not choose     getCombination(v, help, index+1, src, N, M);    //continue the second option }

user: user-4
content: //qplw.cpp #include <stdio.h> #include <string.h> #include <stdlib.h> int v=0; int w=0; int m;//记录字符串长度 int n;//记录字符串中的字符种类数 char map[256];//记录是哪几种字符 int count[256];//记录每种字符有多少个 int stack[1000];//递归用的栈，并记录当前生成的排列 void Make_Map(char *str) {//统计字符串的相关信息     int s[256];     int i;     memset(s,0,sizeof(s));     memset(count,0,sizeof(count));     m=strlen(str);     if (w<1 || m<w) w=m;     while(*str) {         s[*str]++;         str++;     }     n=0;     for (i=0;i<256;i++)         if (s[i]) {             map[n]=i;             count[n]=s[i];             n++;         } } void Find(int depth) {//递归式回溯法生成全排列     if (depth==w) {         int i;         for (i=0;i<depth;i++) putchar(map[stack[i]]);         putchar('\n');     } else {         int i;         if (v && depth>0) {             for (i=0;i<depth;i++) putchar(map[stack[i]]);             putchar('\n');         }         for (i=0;i<n;i++)             if (count[i]) {                 stack[depth]=i;                 count[i]--;                 Find(depth+1);                 count[i]++;             }     } } void main(int argc,char**argv) {     if (argc<2) {         printf("%s 要产生全排列的字符串 [限定长度|-1]\n",argv[0]);         return;     }     if (argc>=3) w=atoi(argv[2]);     if (-1==w) v=1;     Make_Map(argv[1]);     Find(0); } //C:\test>qplw //qplw 要产生全排列的字符串 [限定长度|-1] // //C:\test>qplw 123 //123 //132 //213 //231 //312 //321 // //C:\test>qplw 123 2 //12 //13 //21 //23 //31 //32 // //C:\test>qplw 122333 3 //122 //123 //132 //133 //212 //213 //221 //223 //231 //232 //233 //312 //313 //321 //322 //323 //331 //332 //333 // //C:\test>qplw 123 -1 //1 //12 //123 //13 //132 //2 //21 //213 //23 //231 //3 //31 //312 //32 //321 //

user: user-0
content: 引用 2 楼 uuuououlcz 的回复:P(8,10) = 1814400，百万级别的复杂度了呢，这么大的东西还是建议打印到文件里方便观察，不过这样文件的大小就是1814400 * 10(文本模式打开，加上\r\n的换行) = 18144000B = 18.144MB字节了，有点大了呢，加上递归的消耗目测要是10秒的数量级了哦 嗯嗯 谢谢，不知道这样程序的代码该怎么入手呢？有没什么建议。

user: user-3
content: P(8,10) = 1814400，百万级别的复杂度了呢，这么大的东西还是建议打印到文件里方便观察，不过这样文件的大小就是1814400 * 10(文本模式打开，加上\r\n的换行) = 18144000B = 18.144MB字节了，有点大了呢，加上递归的消耗目测要是10秒的数量级了哦

user: user-5
content: 坛子里 有不少全排列的帖子