这几行代码越看越晕,搞的我头都大了,哪位大侠讲讲?谢谢
输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba
void Permutation(char* pStr, char* pBegin);
/////////////////////////////////////////////////////////////////////////
// Get the permutation of a string,
// for example, input string abc, its permutation is
// abc acb bac bca cba cab
/////////////////////////////////////////////////////////////////////////
void Permutation(char* pStr)
{
Permutation(pStr, pStr);
}
/////////////////////////////////////////////////////////////////////////
// Print the permutation of a string,
// Input: pStr - input string
// pBegin - points to the begin char of string
// which we want to permutate in this recursion
/////////////////////////////////////////////////////////////////////////
void Permutation(char* pStr, char* pBegin)
{
if(!pStr || !pBegin)
return;
// if pBegin points to the end of string,
// this round of permutation is finished,
// print the permuted string
if(*pBegin == '\0 ')
{
printf( "%s\n ", pStr);
}
// otherwise, permute string
else
{
for(char* pCh = pBegin; *pCh != '\0 '; ++ pCh) //这段最不明白???
{
// swap pCh and pBegin
char temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
Permutation(pStr, pBegin + 1);// 递归 什么意思啊
// restore pCh and pBegin
temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
}
}
}
也知道大概的意思,就是不怎么清晰
麻烦大侠赐教,多谢!!奉上最后的50分
[解决办法]
下班了,回去看,帮顶
[解决办法]
abc
acb
bac
bca
cab
cba
规律是大循环遍历所有的元素(a,b,c),在每次遍历的时候发现如果是最后两个元素则交换位置,如果不是则重复遍历和交换的过程(递归)。
[解决办法]
这是典型的回溯法。
for(char* pCh = pBegin; *pCh != '\0 '; ++ pCh) //这段最不明白???
{
// swap pCh and pBegin
char temp = *pCh;//这三句表示改变
*pCh = *pBegin;
*pBegin = temp;
Permutation(pStr, pBegin + 1);// 递归 什么意思啊---在pBegin位更改的情况下,递归将问题变成pBegin+1开始处的全部排列的过程
// restore pCh and pBegin
temp = *pCh;//这三句是回溯结束的扫尾动作,将字符串复原,为的是下一次递归
*pCh = *pBegin;
*pBegin = temp;
}
记住,1.回溯往往都要有记录本次改变,2.递归处理 3.将记录改回来
[解决办法]
for(char* pCh = pBegin; *pCh != '\0 '; ++ pCh) //这段最不明白???--pBegin也是指向pStr的,表示从pStr从pBegin一直到最后循环一道
{
// swap pCh and pBegin--随着pCh从pStr的pBegin到pStr的尾巴,pBegin这个位置排列了所有可能的字符
char temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
Permutation(pStr, pBegin + 1);// 递归 什么意思啊---对于每个pBegin的一个固定选择,再去排列pBegin+1之后的
// restore pCh and pBegin
temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
}
[解决办法]
void Union(char* src, char* tep = NULL) {
if (tep == NULL)
tep = src;
if (!*tep)
cout < <src < <endl;
for (size_t i = 0; i < strlen(tep); ++i)
{
swap(tep[i], tep[0]);
Union(src, ++tep);
--tep;
swap(tep[i], tep[0]);
}
}
int main()
{
char src[] = "abc ";
Union(src);
return 0;
}
[解决办法]
自己设计递归函数的时候,有几点需要注意的:
1、一次调用,要设法将递归的范围缩小或者与递归的目标接近。
2、一次调用,缩小范围或者接近目标之后,必须处于与起始状态相似的条件下,这是为了下一次递归。
3、找到一个递归终结的条件。
下面根据这三点来分析一下void Permutation(char* pStr, char* pBegin)这个递归函数的目的:
1、可以看出Permutation函数的目的为了将从pBegin这个地址开始到 '\0 '结束的字符串进行排列,而参数pStr在递归中根本没有用到,仅仅是为了最终打印结果而已。
所以得到结论,Permutation函数的目的是为了对pBegin起始的字符串进行排列。
2、从那个for循环可以看出,pBegin的第一个字符与其他所有字符都交换了一遍,并且每次交换以后都会继续调用Permutation。因为第一个字符被选择了,那么只剩后面的字符需要排列,这样就缩小了范围,符合注意1。缩小范围之后,又刚好与原先的状况相同,所以符合注意2。
3、至于注意3这条,当然是到 '\0 '结束了(这也是废话)。
4、在这个问题中,因为Permutation的目的仅仅是将第一个字符与其他字符交换来达到遍历的目的,后面的字符排列应该是要交给下一层的Permutation处理的,所以在调用完下一层Permutation的时候,务必将原先交换的字符交换回来,否则与设计Permutation这个函数的初衷就不同了。
另外附加一句,没测试过,不过似乎不交换回来也可以遍历的样子,不过对于设计这个函数的人来说,交换回来思路确实清晰很多。如果让我来写,就算交换回来是多余的,也要画蛇添足一下。