java 打印全排列数列_全排列

本人自己写的代码: /**

*八皇后问题,使用递归的方法来解

*怎么说呢,萌新觉得这题递归的写法和玛雅人的密码那题挺像的(我抄别人的代码)

*萌新就是一张白纸,觉得这种递归很神奇,理由如下

*①递归中使用全局数组,大家一起用一个,每次递归结束后都要恢复全局变量为原值

*②递归中使用一个循环这个我也觉得很骚,印象中自己只会那种if return的语句模式的

*根据数列递推公式写的递归函数

*其他类型语句出现在递归函数中,萌新觉得很神奇。

*在玛雅人的密码那题中,是不断的移位,设置移位的标志变量flag[]来记录是否移位,

*如果已经移位了的话就不对节点进行扩展

*本题中,通过设置标志变量数组flag[]来记录当前字符是否被使用过,

*如果使用过了的话就继续寻找,结果是存在一个全局字符数组res中

*我们可以仔细的思考一下res可能的作用域,

*它的作用域范围绝对不可能是在递归函数里面,

*因为如果在递归函数里声明它的话,递归子层也会声明一个这个数组,

*那么无法做到所有的递归函数都使用同一个数组。

*实际上对于老手来说,他们都不会思考这种萌新才想的事情

*因为不同层的递归都要对这个结果数组进行写操作,

*换言之,它必须被所有层的递归函数共享

*除了全局变量,还有谁能做到这一点???还有谁???

*当然还有另一种放法,在main函数中定义res,

*将它作为参数传给递归函数,递归函数再把res传给它调用的递归函数

*既然是全局变量,那又可以思考一个问题,为什么同样是全局变量,

*凭什么flag[]这个标志数组要还原为原来的值,而res不用

*玛雅人的密码那题,它的循环部分的代码:

*flag[]和str都是全局变量,都需要还原

for(i=0;i

{

if(flag[i]==0)

{

swap(&str[i],&str[i+1]);//交换过后,下次就不再交换,

//如ab 交换后为ba,若不标记下次就有要交换成ab

flag[i]=1;//将该位置标记

find(str,n,k+1);//此次交换过后,k++,进行下一轮判定

swap(&str[i],&str[i+1]);//返回原状

flag[i]=0;

}

}

*理由是str必须要还原,str是搜索过程中前后连贯使用的变量,必须还原

*而res是记录结果的数组,必然不能还原,需求不同,没有比较的必要哈哈

*/

/**

*解题调试过程:

*->编码

*->检查:

*    ①发现忘记将输入的字符进行排序qsort();

*    ②cmp的返回值有问题,忘记了传进来的是指针不是值,不能直接相减

*    ③cur未在main函数中清0,(通过思考res数组的初始值发现)

*    ④

*->编译:

*    错误:新增加的cur= 0;语句的分号达成了中文的分号,产生理由:不详

*    影响:2处error

*    修改后,自测实例通过

*->提交:输出格式不符合要求

*    查看别人的代码,发现每组样例输出结束后要再输出一个回车

*    理解错了样例的意思,以为是每一个排列

*    通过啦!!!开森,回宿舍洗澡去!!!

*/

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

int flag[6];

char res[7];

char ori[7];

int cmp(const void * p1, const void *p2){

char * c1 = (char *)p1;

char * c2 = (char *)p2;

return (*c1 - *c2);//低类型可以自动转化为高类型,不需要(int)进行强制类型转换

}

int cur = 0;

/**

*深入优先搜索的递归算法

*参数:当前的深度,同时也作为数组的下标

*当然深度也可以作为全局变量,在递归调用后恢复原值

*那我就不要参数,使用后一个方法吧

*/

void DFS(){

int len = strlen(ori);//其实len是一直不变的,

//作为全局变量的话可以减少strlen()运算

//不过全局变量的缺点是访问速度不如局部变量快,我暂时是这么认为的

if(cur == len){ //递归的退出条件,当下标=(strlen(ori) - 1)+1

//这么写是为了表示字符串已经存完了,

//该存'\0'了,不存'\0'就不是字符串

//用%s输出就会出错啦

res[cur] = '\0';

printf("%s\n", res);

return ;

}

int i;

for(i = 0; i < len; i++){

if(!flag[i]){ //如果没有被标记,元素未被使用

flag[i] = 1;

res[cur] = ori[i];

cur ++;

DFS();

cur --;

flag[i] = 0;

}

}

}

int main(){

int n;

while(scanf("%s", ori) != EOF){

n = strlen(ori);

cur = 0;

qsort(ori, n, sizeof(char), cmp);

while(n--) flag[n] = 0;

DFS();

printf("\n");

}

return 0;

}

我参考的是Frostime的代码,并在编制上述计算机程序解决问题前,通过此代码,熟悉了一下深度优先搜索的递归函数的运算过程。 #include

#include

#include

#include

using namespace std;

string str;

string res;

bool used[6];

void Dfs(int cur)

{

if (cur == str.length())

{

cout << res << endl;

return;

}

for (int i = 0; i < str.length(); ++i)

{

if (!used[i])

{

//放入

used[i] = true;

res[cur] = str[i];

Dfs(cur + 1);

used[i] = false;

}

}

}

int main()

{

while (cin >> str)

{

sort(str.begin(), str.end());

res = str;

memset(used, false, sizeof(used));

Dfs(0);

cout << endl;

}

}

输入为abc运行的部分过程:

53bad23c398e32f4eb02c437a9d39cc9.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值