【问题描述】已知二叉树的先序遍历序列和中序遍历序列(二叉树中元素类型为字符类型),输出该二叉树的后序遍历序列(采用非递归方式实现)。
【输入形式】二叉树的先序序列 二叉树的中序序列
【输出形式】二叉树的后序序列
【样例输入】ABDEGICFH DBGIEAFHC
【样例输出】
DIGEBHFCA
【样例说明】
【评分标准】
- 创建一个空栈,并将先序序列的第一个元素入栈。
- 初始化一个空字符串,用于保存后序遍历序列。
- 对于先序序列中的每个元素,依次执行以下步骤:
- 如果栈顶元素与中序序列中的当前元素不相等,将先序序列中的当前元素入栈。
- 如果栈顶元素与中序序列中的当前元素相等,说明已经到达一个子树的根节点。
- 将栈顶元素出栈,将其添加到后序序列中。
- 如果栈为空,则结束循环。
- 如果栈不为空,则将栈顶元素出栈,并将其添加到后序序列中。
- 将中序序列中的当前元素与栈顶元素进行比较,直到栈为空或栈顶元素与当前元素不相等。
- 将先序序列中的当前元素入栈。
- 返回后序序列。
#include <iostream>
#include <stack>
#include <string>
using namespace std;
struct Node {
char data;
Node* left;
Node* right;
};
// 根据先序序列和中序序列构建二叉树
Node* buildTree(const string& preorder, const string& inorder) {
if (preorder.empty() || inorder.empty())
return NULL;
// 创建根节点
Node* root = new Node();
root->data = preorder[0];
root->left = NULL;
root->right = NULL;
// 在中序序列中找到根节点的位置
size_t rootIndex = inorder.find(root->data);
// 分割左子树的中序序列和右子树的中序序列
string leftInorder = inorder.substr(0, rootIndex);
string rightInorder = inorder.substr(rootIndex + 1);
// 计算左子树的大小,用于分割先序序列
size_t leftSize = leftInorder.size();
string leftPreorder = preorder.substr(1, leftSize);
string rightPreorder = preorder.substr(leftSize + 1);
// 递归构建左子树和右子树
root->left = buildTree(leftPreorder, leftInorder);
root->right = buildTree(rightPreorder, rightInorder);
return root;
}
// 非递归后序遍历二叉树
void postorderTraversal(Node* root) {
if (root == NULL)
return;
stack<Node*> nodeStack;
Node* current = root;
Node* lastVisited = NULL;
while (current || !nodeStack.empty()) {
if (current) {
// 将左子节点入栈
nodeStack.push(current);
current = current->left;
} else {
Node* topNode = nodeStack.top();
if (topNode->right && topNode->right != lastVisited) {
// 如果存在右子节点且右子节点未被访问过,则转向右子树
current = topNode->right;
} else {
// 否则,访问当前节点并出栈
cout << topNode->data;
nodeStack.pop();
lastVisited = topNode;
}
}
}
}
int main() {
string preorder;
string inorder;
// 获取用户输入的先序序列和中序序列
cout << "Enter the preorder sequence: ";
cin >> preorder;
cout << "Enter the inorder sequence: ";
cin >> inorder;
// 构建二叉树
Node* root = buildTree(preorder, inorder);
// 后序遍历并输出结果
cout << "Postorder traversal: ";
postorderTraversal(root);
cout << endl;
return 0;
}
#include<iostream>
#include<queue>
#include<bits/stdc++.h>
#include<stack>
using namespace std;
string pre,in;
struct Node{
char data;
Node*lchild;
Node*rchild;
};
Node*buildtree(int pl,int pr,int il,int ir)
{
if(pl>pr)
return NULL;
Node*root=new Node();
root->data=pre[pl];
int pos=in.find(pre[pl]);
root->lchild=buildtree(pl+1,pl+pos-il,il,pos-1);
root->rchild=buildtree(pl+pos-il+1,pr,pos+1,ir);
return root;
}
void postorder(Node*root)
{
if(root==NULL)
return;
stack<Node*>stk;
Node*current=root;
Node* lastVisited = NULL;
while(current||!stk.empty())
{
if (current) {
// 将左子节点入栈
stk.push(current);
current = current->lchild;
} else {
Node* topNode = stk.top();
if (topNode->rchild && topNode->rchild != lastVisited) {
// 如果存在右子节点且右子节点未被访问过,则转向右子树
current = topNode->rchild;
} else {
// 否则,访问当前节点并出栈
cout << topNode->data;
stk.pop();
lastVisited = topNode;
}
}
}
}
int main()
{
cin>>pre>>in;
Node*root=buildtree(0,pre.length()-1,0,in.length()-1);
postorder(root);
return 0;
}