目录
复习栈的时候,已知入栈顺序,总是不知道如何列全所有的出栈顺序,因此很苦恼,后来感觉可以用代码来实现,于是上网找了好多,也问了很多AI,但是由于太菜,看不太懂,后来又找了好半天终于在一片文章中得到我能看得懂的思路(又是被自己蠢到的一天)。
思路
对于栈中的当前元素,有以下两种情况:
1.入栈
2.如果栈非空,将当前元素出栈
因此可以用DFS来递归的实现,由于我实在太菜,看文字脑补不出来,因此我画了个图
由图可知我们需要两个数组,分别用来存入栈的数(In数组)和入栈之后又出栈的数(Out数组),由于入栈的数之后出栈是逆序的,所以当枚举完所有的入栈顺序准备出栈时,In数组的元素需要逆序输出,Out数组的元素顺序输出,由于需要逆序操作,DFS过程中需要多次判空,多次访问数组最后一个元素(即计算数组长度),这些单凭数组来实现需要有很多额外变量,因此我用了C++的vector来实现。
以下是我的代码实现:
#include<bits/stdc++.h>
#include<stack>
using namespace std;
const int N=10;
int a[N]; //存入栈数组
vector<int> In; //存入栈但尚未出栈的元素
vector<int> Out; //存出栈的元素
//用vector的原因:需要倒序输出,还需要返回最后一个元素,不能明确知道数组长度
int n;
int cnt;
void dfs(int i)
{
if(i==n) //当遍历到最后一个元素的时候 要将出栈数组顺序输出,入栈数组逆序输出
{
cnt++;
if(!Out.empty())
{
for(int j=0;j<Out.size();j++)
{
cout<<Out[j]<<" ";
}
}
if(!In.empty())
{
for(int j=In.size()-1;j>=0;j--)
{
cout<<In[j]<<" ";
}
}
cout<<endl;
return;
}
In.push_back(a[i]);
dfs(i+1); //入栈
In.pop_back();
if(!In.empty()) //如果有元素已经入栈
{
int pop_val=In.back();
In.pop_back(); //出栈
Out.push_back(pop_val);
dfs(i);
Out.pop_back(); //恢复现场
In.push_back(pop_val);
}
}
int main()
{
//freopen("A.txt","r",stdin);
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
dfs(0);
cout<<cnt<<endl;
return 0;
}
总结
这个代码可以实现已知入栈顺序,列出所有的出栈顺序,也让我对DFS的了解更加深刻,也知道C++的STL库不是摆设,是可以拿来使用和简化代码的好工具。
参考:打印序列的所有出栈顺序(回溯法)及复杂度分析(卡特兰数) - 拾月凄辰 - 博客园 (cnblogs.com)
谢谢大佬的讲解,不过上面代码是我自己看懂后自己写的