一 全排列算法原理和实现
全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。现以{1, 2, 3, 4, 5}为 例说明如何编写全排列的递归算法。
1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。
方法二:
实现方法二:
实现方法三:
全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。现以{1, 2, 3, 4, 5}为 例说明如何编写全排列的递归算法。
1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。
为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。
1. 整形数组
- #include <stdio.h>
- int n = 0;
- void swap(int *a, int *b)
- {
- int m;
- if(*a != *b)
- {
- m = *a;
- *a = *b;
- *b = m;
- }
- }
- void perm(int list[], int k, int m)
- {
- int i;
- if(k >/* == */ m)
- {
- for(i = 0; i <= m; i++)
- printf("%d ", list[i]);
- printf("\n");
- n++;
- }
- else
- {
- for(i = k; i <= m; i++)
- {
- swap(&list[k], &list[i]);
- perm(list, k + 1, m);
- swap(&list[k], &list[i]);
- }
- }
- }
- int main()
- {
- int list[] = {1, 2, 3, 4, 5};
- perm(list,0,sizeof(list) / sizeof(int) - 1);
- printf("total:%d\n", n);
- return 0;
- }
2. 字符串
方法一:
- #include <stdio.h>
- inline void Swap(char& a, char& b)
- {// 交换a和b
- char temp = a;
- a = b;
- b = temp;
- }
- void Perm(char list[], int k, int m)
- { //生成list [k:m ]的所有排列方式
- int i;
- if (k ==/*>*/ m) {//输出一个排列方式
- for (i = 0; i <= m; i++)
- putchar(list[i]);
- putchar('\n');
- }
- else // list[k:m ]有多个排列方式
- // 递归地产生这些排列方式
- for (i=k; i <= m; i++) {
- Swap (list[k], list[i]);
- Perm (list, k+1, m);
- Swap (list [k], list [i]);
- }
- }
- int main()
- {
- char s[]="123";
- Perm(s, 0, 2);
- return 0;
- }
方法二:
从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如此递归处理,从而得到所有元素的全排列。以对字符串abc进行全排列为例,我们可以这么做:以abc为例
固定a,求后面bc的排列:abc,acb,求好后,a和b交换,得到bac
固定b,求后面ac的排列:bac,bca,求好后,c放到第一位置,得到cba
固定c,求后面ba的排列:cba,cab。代码可如下编写所示:
- void swap(char &pCh,char &pBegin)
- {
- char tmp;
- tmp = pCh;
- pCh = pBegin;
- pBegin = tmp;
- }
- void Permutation(char* pStr, char* pBegin)//pStr与pBegin相同
- {
- if(!pStr || !pBegin)
- return;
- if(*pBegin == '\0')
- {
- printf("%s\n", pStr);
- }
- else
- {
- for(char* pCh = pBegin; *pCh != '\0'; ++ pCh)
- {
- // swap pCh and pBegin
- swap(*pCh,*pBegin);
- Permutation(pStr, pBegin + 1);
- // restore pCh and pBegin
- swap(*pCh,*pBegin);
- }
- }
- }
- int main()
- {
- char str[] = "123";
- Permutation(str,str);
- return 0;
- }
二 组合的原理与算法
题目:输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有 、a、b、c、ab、ac、bc、abc。
分析:假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;二是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。下面是这种思路的参考代码:
实现方法一:
- #include <stdio.h>
- #include <vector>
- using namespace std;
- void _Combination(const char* string, vector<char>& result)
- {
- if(*string == '\0')
- {
- vector<char>::iterator iter = result.begin();
- for(; iter < result.end(); ++ iter)
- printf("%c", *iter);
- printf("\n");
- return;
- }
- result.push_back(*string);
- _Combination(string + 1, result);
- result.pop_back();
- _Combination(string + 1, result);
- }
- void Combination(char* string)
- {
- if(string == NULL)
- return;
- vector<char> result;
- _Combination(string, result);
- }
- void main()
- {
- char *pString = "abc";
- Combination(pString);
- }
- #include <stdio.h>
- #include <vector>
- using namespace std;
- void _Combination(const char* string, int number, vector<char>& result)
- {
- if(number == 0)
- {
- vector<char>::iterator iter = result.begin();
- for(; iter < result.end(); ++ iter)
- printf("%c", *iter);
- printf("\n");
- return;
- }
- if(*string == '\0')
- return;
- result.push_back(*string);
- _Combination(string + 1, number - 1, result);
- result.pop_back();
- _Combination(string + 1, number, result);
- }
- void Combination(char* string)
- {
- if(string == NULL)
- return;
- int length = strlen(string);
- vector<char> result;
- for(int i = 0; i <= length; ++ i)
- {
- _Combination(string, i, result);
- }
- }
- void main()
- {
- char *pString = "abc";
- Combination(pString);
- }
- #include <stdio.h>
- #include <iostream.h>
- int combine(int a[],int n,int m)
- {
- m = m > n ?n:m;
- int * order =new int [m +1];
- for(int i = 0; i <= m; i ++)
- order[i] = i - 1;
- int count = 0;
- int k = m;
- bool flag = true;
- while(order[0] == -1)
- {
- if(flag)
- {
- for(i = 1; i <= m; i ++)
- cout<<a[order[i]]<<" ";
- cout<<endl;
- count ++;
- flag =false;
- }
- order[k] ++;
- if(order[k] == n)
- {
- order[k --] = 0;
- continue;
- }
- if(k < m)
- {
- order[++ k] = order[k - 1];
- continue;
- }
- if(k == m)
- flag = true;
- }
- delete[] order;
- return count;
- }
- void main()
- {
- int a[] = {1,2,3,4,5,6,7};
- int len = sizeof(a) / sizeof(int);
- int sum = 0;
- for(int i = 0;i <= len;i ++)
- sum += combine(a,len,i);
- printf("sum = %d\n",sum);
- }
注明:以上部分转载http://zhedahht.blog.163.com/blog/static/2541117420114172812217/,在此表示感谢!