二叉树结构
算法思想(先说后续遍历)
关键点在构建的栈,可以先看下结构
//定义栈
struct SqStack {
TreeNode data[MaxSize];
int flag[MaxSize];
int top;
};
data就是存放树节点类型,没什么特别的,flag是标记栈内节点是否被访问过【0代表没有当前节点,-1表示没有访问过,1代表访问过】;初始化把根节点压栈,之后先出栈,如果没有访问,那么看下是否有左右孩子,有的话【根,右孩子,左孩子】依次入栈,这是根节点就被标记为访问过;如果没有孩子节点则访问该节点即可;外面加层循环用于遍历栈。
编程实现(C++)
#include <iostream>
using namespace std;
#define MaxSize 30
//二叉树树节点信息
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x = 0) : val(x), left(NULL), right(NULL) {}
};
//定义栈
struct SqStack {
TreeNode data[MaxSize];
int flag[MaxSize];
int top;
};
SqStack S;
//栈相关操作
//初始化
void InitStack(SqStack &s) {
s.top = -1;
for (int i = 0; i < MaxSize; i++) {
s.flag[i] = 0;
}
}
//栈判空
bool StackEmpty(SqStack s) {
if (s.top == -1) {
return true;
} else {
return false;
}
}
//进栈
bool Push(SqStack &s, TreeNode x, int yesOrNo) {
if (s.top == MaxSize - 1) {
return false;
}
++s.top;
s.data[s.top] = x;
s.flag[s.top] = yesOrNo;
return true;
}
//出栈
bool Pop(SqStack &s, TreeNode &x) {
if (s.top == -1) {
return false;
}
x = s.data[s.top];
s.flag[s.top] = 0;
s.top--;
return true;
}
int getTopState(SqStack &s) {
return s.flag[s.top];
}
//访问节点
void Visit(TreeNode *T) {
cout << T->val << " ";
}
//后续遍历的非递归形式
void PostOrder(TreeNode *T) {
InitStack(S);
TreeNode t;
Push(S, *T, -1);
int flag;
while (!StackEmpty(S)) {
flag = getTopState(S);
Pop(S, t);
if (flag == -1 && (t.right || t.left)) {
Push(S, t, 1);
if (t.right) Push(S, *t.right, -1);
if (t.left) Push(S, *t.left, -1);
} else {
Visit(&t);
}
}
}
int main() {
//构建二叉树
TreeNode t11(1);
TreeNode t12(2);
TreeNode t13(3);
TreeNode t14(4);
TreeNode t15(5);
TreeNode t16(6);
TreeNode t17(7);
TreeNode *t1 = &t11;
t11.left = &t12;
t11.right = &t13;
t12.left = &t14;
t13.left = &t15;
t12.right = &t16;
t13.right = &t17;
PostOrder(t1);
return 0;
}
结果展示
中序遍历
只需要把while循环体改成如下:
while (!StackEmpty(S)) {
flag = getTopState(S);
Pop(S, t);
if (flag == -1 && (t.right || t.left)) {
if (t.right) Push(S, *t.right, -1);
Push(S, t, 1);
if (t.left) Push(S, *t.left, -1);
} else {
Visit(&t);
}
}
只是把Push(S, t, 1);
放到中间即可
先序遍历
while (!StackEmpty(S)) {
flag = getTopState(S);
Pop(S, t);
if (flag == -1 && (t.right || t.left)) {
if (t.right) Push(S, *t.right, -1);
if (t.left) Push(S, *t.left, -1);
Push(S, t, 1);
} else {
Visit(&t);
}
}
只是把Push(S, t, 1);
放到最后即可