题意
根据题目给定的等价于中序序遍历的栈操作,还原出该二叉树,并将其后序序列输出
注意点
- 先序遍历的压栈的值不一定是从1到n的连续整数
- 也可以用string容器读入push或pop指令
题解
解题思路:
①观察到入栈顺序是该二叉树的先序序列,而出栈顺序是该二叉树的中序序列
②由题目数据得出先序序列和中序序列
③定义函数create由先序、中序序列构建一棵二叉树
④后序遍历该二叉树,输出后序序列
静态数组:
#include <string.h>
#include <stdio.h>
#include <stack>
using namespace std;
const int maxn = 70;
struct node {
int data;
int lchild, rchild;
}Node[maxn];
//新建结点
int rang = 0;
int newNode(int v) {
Node[rang].data = v;
Node[rang].lchild = -1;
Node[rang].rchild = -1;
return rang++;
}
//变量
int n, in[maxn], pre[maxn];
//由中序序列和先序序列构建二叉树
int create(int preL, int preR, int inL, int inR) {
if (preL > preR) {
return -1;
}
int root = newNode(pre[preL]);
int k;
//在中序序列中找到根节点
for (k = inL; k <= inR; k++) {
if (in[k] == pre[preL]) {
break;
}
}
int numLeft = k - inL;
//左子树的先序区间为[preL+1, preL + numLeft],中序区间为[inL, k-1]
Node[root].lchild = create(preL+1, preL+numLeft, inL, k-1);
//右子树的先序区间为[preL+numLeft+1, preR],中序区间为[k+1, inR]
Node[root].rchild = create(preL+numLeft+1, preR, k+1, inR);
return root;
}
//后序遍历二叉树
bool flag = false;
void postorder(int root) {
if (root == -1) {
return;
}
postorder(Node[root].lchild);
postorder(Node[root].rchild);
if (flag) printf(" ");
printf("%d", Node[root].data);
flag = true;
}
int main() {
stack<int> st;
int inIndex = 0, preIndex = 0;
char str[5];
scanf("%d", &n);
//获取中序序列
for (int i = 0; i < 2 * n; i++) {
scanf("%s", str);
if (strcmp(str, "Push") == 0) {
int temp;
scanf("%d", &temp);
pre[preIndex++] = temp;
st.push(temp);
} else {
in[inIndex++] = st.top();
st.pop();
}
}
//由中序序列和先序序列构建二叉树
int root = create(0, n-1, 0, n-1);
//后序遍历二叉树
postorder(root);
printf("\n");
return 0;
}
链表:
#include <string.h>
#include <stdio.h>
#include <stack>
using namespace std;
const int maxn = 50;
struct node {
int data;
node* lchild, * rchild;
};
//新建结点
node* newNode(int v) {
node* Node = new node;
Node->data = v;
Node->lchild = NULL;
Node->rchild = NULL;
return Node;
}
//变量
int n, in[maxn], pre[maxn];
//由中序序列和先序序列构建二叉树
node* create(int preL, int preR, int inL, int inR) {
if (preL > preR) {
return NULL;
}
node* root = newNode(pre[preL]);
int k;
//在中序序列中找到根节点
for (k = inL; k <= inR; k++) {
if (in[k] == pre[preL]) {
break;
}
}
int numLeft = k - inL;
//左子树的先序区间为[preL+1, preL + numLeft],中序区间为[inL, k-1]
root->lchild = create(preL+1, preL+numLeft, inL, k-1);
//右子树的先序区间为[preL+numLeft+1, preR],中序区间为[k+1, inR]
root->rchild = create(preL+numLeft+1, preR, k+1, inR);
return root;
}
//后序遍历二叉树
bool flag = false;
void postorder(node* root) {
if (root == NULL) {
return;
}
postorder(root->lchild);
postorder(root->rchild);
if (flag) printf(" ");
printf("%d", root->data);
flag = true;
}
int main() {
scanf("%d", &n);
stack<int> st;
int temp, preIndex = 0, inIndex = 0;
char str[5];
//获取中序序列
for (int i = 0; i < 2 * n; i++) {
scanf("%s", str);
if (strcmp(str, "Push") == 0) {
scanf("%d", &temp);
pre[preIndex++] = temp;
st.push(temp);
} else {
in[inIndex++] = st.top();
st.pop();
}
}
//由中序序列和先序序列构建二叉树
node* root = create(0, n-1, 0, n-1);
//后序遍历二叉树
postorder(root);
printf("\n");
return 0;
}