其实我对堆栈和递归的理解还是很不到位的,只意识到了系统栈大小和dfs序这一层面,惭愧呀惭愧。
转载一篇文章,讲得比较清楚。https://www.cnblogs.com/holmestian/p/3928136.html
前一段时间总结了全排列问题的几种递归解法,今天再总结一下如何通过对系统栈行为的模拟来非递归的实现全排列问题。
我们用一个数组stack[]来表示一个栈,用一个top指针来表示栈顶,用一个flags[]数组来标示每一个数字的可用性;用i来表示当前的状态。
初始状态top=0;i=-1;flags数组全为1;
i递增,如果i没有越界并且flags[i]==1,那么就将i写入栈中,栈顶往前移动一位;最后把flags[i]赋值为0,i回溯到初始状态-1;
当栈顶越界,就将整个栈的信息打印出来,然后top指针回退1,i回归栈顶的状态,flags[i]标记为1;
当i越界,意味着当前栈顶的状态已经穷尽,应该将该元素弹出栈,即top--;然后i回归到栈顶的状态,flags[i]标记为1;
最后,当栈中元素全被弹出,栈顶和栈底相遇,则所有状态全被穷尽。
语言描述的有点抽象,可以根据这个在纸上画画图,这整个过程就是系统栈的行为过程。主要的点就是每次栈顶的变化都伴随i的变化,i要回溯到前一个状态
#include <iostream>
using namespace std;
int stack[100];
int flags[50];
void printStack(int* stack,int n){
for (int i=0; i<n; i++)
cout<<stack[i]+1;
cout<<endl;
}
void perm(int n){
int top=0;
int i=-1;
while (true) {
i++;
if (i==n) {
if (top==0) {
break;
}else{
top--;
i=stack[top];
flags[i]=1;
}
}else if(flags[i]==1){
flags[i]=0;
stack[top]=i;
top++;
i=-1;
}
if(top==n){
top--;
i=stack[top];
flags[i]=1;
printStack(stack, n);
}
}
}
int main()
{
int n=4;
for(int i=0;i<50;i++)
flags[i]=1;
perm(n);
return 0;
}