满意答案
gbmdnx374
2016.08.23
采纳率:49% 等级:12
已帮助:9001人
我的G++编译器上一切正常,是不是数组太小输入的数越界了,第一个return可以不写,只要把后面循环部分放在if的else部分里即可达到和return一样效果
book[i]这个数组记录的是当前i处的数字有没有用过,因为全排列是全不重复的
当DFS时,判断当前循环变量所代表的数字有没有在排列中出现,已经出现,就跳过(防止出现5 5 5 5 5 之类情况)
如果没有出现过,把这位数字压入排列,这位数字的book[i]赋值为1,代表用过,然后dfs下一位,然后再清除book[i],这是一个回溯的过程,因为 for(i=1;i<=n;i++) 这个循环会遍历所有可能取的数,不能因为第一种情况取了5 1 循环到2的时候 5 2 这种情况下 1 还是被使用 , 所以显然要清掉1的使用, 这两种情况是相互并列, 结论是 这种回溯的过程一般在DFS之后进行 , 清除这一次DFS对整体状态的影响,让函数回到这一次调用DFS之前的状态追问: 我还是不太明白。那两个return删除后,编译正常。输入3会出现它的全排序。还有那个dfs(step+1);book[i]=0;知道是什么意思,就是不知道它运行顺序。例如第一次a[1]=1之后a[2]=2然后a[3]=3,然后输出全排列123,那它是什么时候运行book[i]=0的?
追答: 就用3这个例子
一开始a数组是空的
先循环到1 压一个进去 , 然后dfs(1)没结束,开始了dfs(2) 这个函数里 ,循环第一次到数字1的时候已经使用过了 所以跳到2 把2压入a数组 , 然后开始dfs(3) ,同理 dfs(3)这次压了一个3进去 , 开始dfs(4) ,这个时候满足了 step==n+1的条件开始输出所有的数 , 然后dfs(4)返回 , 回到dfs(3)里 , dfs(3)执行下面的book[3]=0 , 把本来用了的3清空, 然后循环走到头 , 函数返回 , 回到dfs(2),把2的使用清除, 然后循环到3,这时候把3压进去, 开始dfs(3),这时候在dfs(3)里,2还没有被使用, 所以这次会压入2 , 开始dfs(4),然后开始输出,然后返回,运行book[i]=0, 再返回,再运行一次,直到返回到dfs(2),这次的dfs(2)里的循环也到头了,继续返回到dfs(1),再执行一次,这次循环走到2,把2压进去, 这是2是头一个数,依次进行上面的过程
所以最终结果是
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
也就是说,在递归返回的时候,也就是dfs(step+1);这个上面的语句彻底结束的时候才会执行book[i]=0,彻底结束在这里是指运行到dfs(n+1)然后层层返回
10分享举报