完整代码在最底下⬇️
题目描述
求一颗树的后序遍历的非递归算法
要求:必须是非递归算法,使用堆栈对象来实现
建树方法采用“先序遍历+空树用0表示”的方法
输入
第一行输入一个整数t,表示有t个测试数据
第二行起输入二叉树先序遍历的结果,空树用字符‘0’表示,输入t行
3
AB0C00D00
ABC00D00EF000
ABCD0000E0F00
输出
逐行输出每个二叉树的后序遍历结果
CBDA
CDBFEA
DCBFEA
题目给的算法
讲真的,没仔细看,也看不懂(
解题思路
我的理解是:遍历部分不能用递归而是用堆栈。但既然不用递归了那就都不用递归,建树也用栈来建。
建树
首先初始化root,赋值、入栈。
flag是标记要建立左子树还是右子树还是左右子树都建立好了。0是左,1是右,2是完成。
case 0建立左子树
如果当前pos位置上的是‘0’,左子树赋为空,flag=1;
不是‘0’,左子树不为空,flag=0表示后序要建立结点的左右子树,建立newNode,并赋为p的左结点。如果栈顶不是p(加了个if判断是为了防止重复入栈),则p入栈,p指向newNode也就是p的左结点。
case 0: {
//建立左子树
if(str[pos] == '0') {
p->leftChild = nullptr;
flag = 1;
} else {
flag = 0;
newNode->data = str[pos];
p->leftChild = newNode;
if(initial.top() != p) {
initial.push(p);
}
p = newNode;
}
pos++;
break;
}
case 1建立右子树
到这一步,不管是不是‘0’,当前结点都算建立完成,built赋为1;
如果是0,flag=2,其他的和case 0一样。
case 1: {
//建立右子树
p->built = 1;
if(str[pos] == '0') {
p->rightChild = nullptr;
flag = 2;
} else {
flag = 0;
newNode->data = str[pos];
p->rightChild = newNode;
if(initial.top() != p) {
initial.push(p);
}
p = newNode;
}
pos++;
break;
}
case 2 建立完成
p指向栈顶
如果p指向的结点已经建立完毕,则flag仍为2,栈顶出栈;
否则是p的左子树建立完成,还要建立右子树,flag = 1。
case 2: {
p = initial.top();
if(p->built == 1) {
flag = 2;
initial.pop();
} else {
flag = 1;
}
break;
}
后序遍历
若p不为空且visit = 0,则p入栈,visit赋为1,p指向左子树,知道找到最左端的结点
若p不为空,则p指向s栈栈顶(不出栈),并且此时p的右子树不为空,则p = p->rightChild,否则输出p的值;此时再出栈,p指向栈顶。
void Tree::postOrder() {
Node* p = root;
while(true) {
if(p && p->visit == 0) {
s.push(p);
p->visit = 1;
p = p->leftChild;
} else {
p = s.top();
if(p->rightChild && p->rightChild->visit == 0) {
p = p->rightChild;
} else {//输出
cout << p->data;
s.pop();
if(s.empty()) {
break;
}
p = s.top();
}
}
}
cout << endl;
}
完整代码
#include <iostream>
#include <stack>
using namespace std;
class Node {
public:
char data{};
int visit{};//后序遍历访问标记
int built{};//标记左右子树已建立
Node *leftChild, *rightChild;
Node() : leftChild(nullptr), rightChild(nullptr) {}
};
class Tree {
private:
string str{};
int pos{};
Node* root{};
stack<Node*> initial;//建树栈
stack<Node*> s;//遍历栈
void build();
public:
Tree();
void postOrder();
};
Tree::Tree() {
cin >> str;
pos = 0;
build();
}
void Tree::build() {
//非递归建立二叉树
root = new Node;
root->data = str[pos++];
initial.push(root);
Node* p = root;
int flag = 0;//0左1右2完
while(pos <= str.size() && !initial.empty()) {
Node *newNode = new Node;
switch(flag) {
case 0: {
//建立左子树
if(str[pos] == '0') {
p->leftChild = nullptr;
flag = 1;
} else {
flag = 0;
newNode->data = str[pos];
p->leftChild = newNode;
if(initial.top() != p) {
initial.push(p);
}
p = newNode;
}
pos++;
break;
}
case 1: {
//建立右子树
p->built = 1;
if(str[pos] == '0') {
p->rightChild = nullptr;
flag = 2;
} else {
flag = 0;
newNode->data = str[pos];
p->rightChild = newNode;
if(initial.top() != p) {
initial.push(p);
}
p = newNode;
}
pos++;
break;
}
case 2: {
p = initial.top();
if(p->built == 1) {
flag = 2;
initial.pop();
} else {
flag = 1;
}
break;
}
default:
break;
}
}
}
void Tree::postOrder() {
Node* p = root;
while(true) {
if(p && p->visit == 0) {
s.push(p);
p->visit = 1;
p = p->leftChild;
} else {
p = s.top();
if(p->rightChild && p->rightChild->visit == 0) {
p = p->rightChild;
} else {//输出
cout << p->data;
s.pop();
if(s.empty()) {
break;
}
p = s.top();
}
}
}
cout << endl;
}
int main() {
int t;
cin >> t;
while(t--) {
Tree tree;
tree.postOrder();
}
return 0;
}