今天刷到这一题,猛一下以为挺简单的,经过简单思考,以为在层序遍历时使用堆栈即可,天真的我代码写完才发现结果不对。经过仔细思考,发现可以用双端队列来实现。但是一写发现不是那么回事,可能是状态不佳,可能是真的笨。。。太绕人了!差点写吐了,人给我写傻了。经过我的手动模拟发现双端队列确实可以做,不甘心的我还是花了两个小时左右给干出来了。考试肯定不能这样干,于是我决定使用其它方法实现,但两个小时的努力不能白费,所以把代码记录下来。
#include <stdio.h>
#include <deque>
#include <algorithm>
using namespace std;
const int maxn = 33;
int in[maxn], post[maxn];
int n, cnt = 0; //n:结点个数 cnt:用来记录输出空格和换行
struct Node{
int data, height;
Node *lchild, *rchild;
};
Node *create(int inL, int inR, int postL, int postR, int height)
{//建树
if(postL > postR){
return NULL;
}
Node *root = new Node;
root->data = post[postR];
root->height = height;
root->lchild = root->rchild = NULL;
int k;//在中序序列中找到根节点位置
for(k=inL; k<inR; k++){
if(in[k]==post[postR]){
break;
}
}
int numL = k-inL;//左子树结点个数
root->lchild = create(inL, k-1, postL, postL+numL-1, height+1);
root->rchild = create(k+1, inR, postL+numL, postR-1, height+1);
return root;
}
void zigZag(Node *root)
{
deque<Node*> dq;
dq.push_back(root);
int turn = 1; //用来切换双端队列操作方向,直到每一层结点处理完才切换方向
while(!dq.empty()){
Node *front = dq.front();
Node *back = dq.back();
if(turn==1){
if(back->height%2==1){ //尾部出队,先右孩子头部进队,再左孩子头部进队
Node *now = dq.back();
dq.pop_back();
cnt++;
printf("%d", now->data);
if(cnt<n){
printf(" ");
}else{
printf("\n");
}
if(now->rchild) dq.push_front(now->rchild);
if(now->lchild) dq.push_front(now->lchild);
}else{
turn = -1; //处理完一层结点,切换方向
}
}else{
if(front->height%2 == 0){//头部出队,先左孩子尾部进队,再右孩子尾部进队
Node *now = dq.front();
dq.pop_front();
cnt++;
printf("%d", now->data);
if(cnt<n){
printf(" ");
}else{
printf("\n");
}
if(now->lchild) dq.push_back(now->lchild);
if(now->rchild) dq.push_back(now->rchild);
}else{
turn = 1;
}
}
}
}
int main()
{
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d", &in[i]);
}
for(int i=0; i<n; i++){
scanf("%d", &post[i]);
}
Node *root = create(0, n-1, 0, n-1, 1);
zigZag(root);
return 0;
}
PS:修改之后的正常代码(比之前写的轻松多了):
#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 33;
int in[maxn], post[maxn];
int n, cnt = 0; //n:结点个数 cnt:用来记录输出空格和换行
struct Node{
int data, height;
Node *lchild, *rchild;
};
Node *create(int inL, int inR, int postL, int postR, int height)
{//建树
if(postL > postR){
return NULL;
}
Node *root = new Node;
root->data = post[postR];
root->height = height;
root->lchild = root->rchild = NULL;
int k;//在中序序列中找到根节点位置
for(k=inL; k<inR; k++){
if(in[k]==post[postR]){
break;
}
}
int numL = k-inL;//左子树结点个数
root->lchild = create(inL, k-1, postL, postL+numL-1, height+1);
root->rchild = create(k+1, inR, postL+numL, postR-1, height+1);
return root;
}
int maxHeight = 0;
vector<Node*> ans[maxn];//记录每一层结点
void BFS(Node *root)
{
queue<Node*> q;
q.push(root);
while(!q.empty()){
Node *front = q.front();
q.pop();
if(front->height>maxHeight){
maxHeight = front->height;
}
ans[front->height].push_back(front);
if(front->lchild) q.push(front->lchild);
if(front->rchild) q.push(front->rchild);
}
}
int main()
{
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d", &in[i]);
}
for(int i=0; i<n; i++){
scanf("%d", &post[i]);
}
Node *root = create(0, n-1, 0, n-1, 1);
BFS(root);
for(int i=1; i<=maxHeight; i++){
if(i%2==1){//奇数层倒着输出
for(int j=ans[i].size()-1; j>=0; j--){
printf("%d", ans[i][j]->data);
cnt++;
if(cnt<n) printf(" ");
else printf("\n");
}
}else{
for(int j=0; j<ans[i].size(); j++){
printf("%d", ans[i][j]->data);
cnt++;
if(cnt<n) printf(" ");
else printf("\n");
}
}
}
return 0;
}