读书人

这几行代码越看越晕搞的小弟我头都大

发布时间: 2012-02-11 09:51:34 作者: rapoo

这几行代码越看越晕,搞的我头都大了,哪位大侠讲讲?谢谢
输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串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这个函数的初衷就不同了。

另外附加一句,没测试过,不过似乎不交换回来也可以遍历的样子,不过对于设计这个函数的人来说,交换回来思路确实清晰很多。如果让我来写,就算交换回来是多余的,也要画蛇添足一下。

读书人网 >C++

热点推荐