一、 递归版本
1、算法简述
简单地说:就是第一个数分别以后面的数进行交换
E.g:E = (a , b , c),则 prem(E)= a.perm(b,c)+ b.perm(a,c)+ c.perm(a,b)
然后a.perm(b,c)= ab.perm(c)+ ac.perm(b)= abc + acb.依次递归进
好了,知道算法之后就不难编出一份好的代码了。
#include<iostream>
using namespace std;
void swap(char *a, char *b)
{
char c;
c = *a;
*a = *b; *b = c;
}
//需要三个参数,k表示当前的数,m表示数的个数
void per(char *a, int k, int m)
{
if (k == m)
{
static int sum = 1;
cout << "第" << sum++ << "全排列" << a << endl;
}
else
{
for (int i = k; i <= m; i++) //第i个数分别与它后面的数字交换就能得到新的排列
{
swap(a + k, a + i);
per(a, k + 1, m);
swap(a + k, a + i);
}
}
}
int main()
{
char a[] = {'1', '2', '3', '4'};
per(a, 0, 3);
return 0;
}
OK,见图知情况
但是上面代码有个缺陷:两个相同的数也进行了交换,见下图:
去掉重复符号的全排列:在交换之前可以先判断两个符号是否相同,不相同才交换,这个时候需要一个判断符号是否相同的函数。
代码如下:
#include<iostream>
using namespace std;
void swap(char *a, char *b)
{
char c;
c = *a;
*a = *b; *b = c;
}
bool Isswap(char *a, int k, int i)
{
if (k ==i)
{
return true;
}
if (a[k] == a[i])
{
return false;
}
else
{
return true;
}
}
//需要三个参数,k表示当前的数,m表示数的个数
void per(char *a, int k, int m)
{
if (k == m)
{
static int sum = 1;
cout << "第" << sum++ << "全排列" << a << endl;
}
else
{
for (int i = k; i <= m; i++) //第i个数分别与它后面的数字交换就能得到新的排列
{
if (Isswap(a, k, i))
{
swap(a + k, a + i);
per(a, k + 1, m);
swap(a + k, a + i);
}
}
}
}
int main()
{
char a[] = {'1', '2', '3', '4'};
per(a, 0, 3);
return 0;
}