提交代码
//这道题在看陈越老师的数据结构时候已经做过了,现在又做了一遍,感觉也是不同了,这次对树的遍历又有了更深的理解,这次栈也没用,
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<stack> #include<algorithm> using namespace std; const int maxn=1000007; typedef long long ll; template<class T>inline T read(T&x) { char c; while((c=getchar())<=32); bool f=false; if(c=='-')f=true,c=getchar(); for(x=0; c>32; c=getchar())x=x*10+c-'0'; if(f)x=-x; return x; } template<class T>inline void write(T x) { if(x<0)putchar('-'); else if(x<10)putchar(x+'0'); else write(x/10),putchar(x%10+'0'); } template<class T>inline void writeln(T x) { write(x); puts(""); } //--------IO template-------------------- #define lson (root<<1)//左儿子 #define rson ((root<<1)+1)//右儿子 int a[maxn];//存树的节点 bool vis[maxn];//标记节点是否访问过,因为树在遍历时回溯的时候会用到 int first=1; void post(int root) { if(a[lson]!=-1)post(lson); if(a[rson]!=-1)post(rson); if(first)printf("%d",a[root]),first=0; else printf(" %d",a[root]); } int main() { int n,m,i,j,k,t,x; read(n); m=n<<1; memset(a,-1,sizeof(a)); char op[5]; int root=1; int ok=0; for(i=0;i<m;i++) { scanf("%s",op); if(strcmp(op,"Push")==0) { read(x); if(a[root]!=-1)//是回溯的回来访问的,这时读入的节点必然是这个节点的右儿子 { root=rson;//找到有儿子 a[root]=x;//赋值 root=lson;//root更新到左儿子,因为输入的时候先序 } else //不是回溯访问的 ,那么就是第一次访问的,所以这个时候节点的值就是他 { a[root]=x;//节点赋值 root=lson;//root更新到左儿子 } } else { root/=2;//pop就是回溯,所以回到父亲的节点 x=a[root]; while(vis[x])//判断是不是已经访问过了,如果访问过了,那么还要继续回溯到第一个没有访问的节点,这个由样例的4到1,而不是4再到2了 {2 root/=2; x=a[root]; } if(!vis[x])vis[x]=1;//标记访问过的 } } post(1);//后序遍历 ,比较简单了,直接递归 printf("\n"); return 0; }