还记得高中刚学排列组合时候被排列组合玩的团团转,虽然最终没有逃出我的魔爪。。
自认为做排列组合的题目是在给学习搜索做个准备工作,很显然,刚刚开始的时候它们对我不甚友好,表示现在仍然 心存芥蒂。所以果断回来复习一下。。当然我说的是全排列
全排列
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排 列。当m=n时所有的排列情况叫全排列。
eg:输出3的全排列:1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
(看见百度上面好多种方法,感觉很高大上的样子,只是记下来我理解的东东)
用递归标记的方法打印出n的全排列,以3为例,首先a数组存的数为1 2 3,另外一个数组b用于输出不同的排列,flag数组用于标记数是否打印过。
#include <stdio.h>
#include <stdlib.h>
int a[100];
int b[100];
int flag[100];
int n;
void fun(int num)
{
int i;
if(num == n) //当b中的数num == n之后就可以输出一个排列
{
for(i=0; i<n; i++)
{
printf("%d ", b[i]);
}
printf("\n");
return ;
}
else
{
for(i=0; i<n; i++)
{
if(!flag[i]) //如果flag[i] == 0 也就是a[i]这个数还没有被打印过,就让b[num] = a[i]
{
flag[i] = 1; //将填过的数进行标记,保证在b没有输出之前已经填过的a[i]不会在出现在b中
b[num] = a[i];
fun(num+1); //向下递归,填b[num+1]
flag[i] = 0; //取消标记,用于下一轮的排列
}
}
}
}
int main()
{
while(scanf("%d", &n) != 0)
{
int i;
for(i=0; i<n; i++)
{
a[i] = i+1;
}
fun(0);
}
return 0;
}
正常来说这种方式更容易记住,就是可能刚开始标记的时候会觉得乱七八糟的,但是后来会比较实用。。
下一种方式,按我的思维来说更容易理解一点,但是代码实现起来稍稍的麻烦一点,也不容易记住,略过了。。
(就是进行两个两个的交换)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int change(char *p, char *q)
{
char temp;
temp = *p;
*p = *q;
*q = temp;
return 0;
}
int fun(char *pstr, int m, int n)
{
int i;
if(m == n)
{
printf("%s\n", pstr);
}
else
{
for(i=m; i<=n; i++)
{
change(pstr+m, pstr+i);
fun(pstr, m+1, n);
change(pstr+m, pstr+i);
}
}
return 0;
}
int output(char *pstr)
{
fun(pstr, 0, strlen(pstr)-1);
return 0;
}
int main()
{
char pstr[ ] = "123";
output( pstr );
return 0;
}