144. Binary Tree Preorder Traversal
94. Binary Tree Inorder Traversal
145. Binary Tree Postorder Traversal
二叉树遍历的递归写法可以说是十分简单,之所以简单是因为不需要人来维护栈,倘若让你显式地将这个栈模拟出来,事情就未必有你想的那样简单了。 -e-
#include<iostream>
#include<stack>
using namespace std;
#define ElemType char
typedef struct TreeNode {
ElemType val;
TreeNode * left;
TreeNode * right;
} * BiTree;
void createBiTree(BiTree& root) {
char ch = cin.get();
if (' ' == ch)
return;
root = (BiTree)malloc(sizeof(TreeNode));
root->val = ch;
createBiTree(root->left);
createBiTree(root->right);
return;
}
void inorderTraverseRecursive(BiTree& root) {
if (!root)
return;
inorderTraverseRecursive(root->left);
cout << root->val;
inorderTraverseRecursive(root->right);
return;
}
// 二叉树的前序遍历(非递归)
void preorderTraversal(BiTree root) {
stack<BiTree> stk;
while (root || !stk.empty()) {
while (root) {
stk.push(root);
cout << root->val;
root = root->left;
}
root = stk.top();
stk.pop();
root = root->right;
}
}
// 二叉树的中序遍历(非递归)
void inorderTraversal(BiTree root) {
stack<BiTree> stk;
// 请思考while的条件表达式为什么这样写
// 1. 初始时栈是空的
// 2. 在根结点退栈后根结点入栈前这个时间段,栈是空的
while (root || !stk.empty()) {
while (root) {
stk.push(root);
root = root->left;
}
root = stk.top();
cout << root->val;
stk.pop();
root = root->right;
// 有没有发现这句其实还包含了root = nullptr;
}
}
// 二叉树的后序遍历(非递归)
void postorderTraversal(BiTree root) {
stack<BiTree> stk;
BiTree pre = nullptr;
// 请思考while的条件表达式为什么这样写
// 1. 初始时栈是空的
while (root || !stk.empty()) {
while (root) {
stk.push(root);
root = root->left;
}
root = stk.top();
// 若此结点有右孩子,并且此右孩子未被访问
// 则应当令此右孩子入栈
if (root->right && root->right!=pre) {
root = root->right;
}
// 若此结点无右孩子,或者该右孩子已被访问过
// 则说明该结点的左右子树都已被访问
// 令此结点出栈, 并且访问它
else {
cout << root->val;
stk.pop();
pre = root;
root = nullptr; // 防止已出栈的指针再次进栈
}
}
}
int main() {
BiTree root;
createBiTree(root);
inorderTraverseRecursive(root);
cout << endl << "--------------" << endl;
inorderTraversal(root);
cout << endl << "--------------" << endl;
preorderTraversal(root);
cout << endl << "--------------" << endl;
postorderTraversal(root);
return 0;
}
三种遍历方式本质上其实都一样,只是访问根结点的时机不同(对于后序遍历还应判断该不该访问这个根结点)
指针进栈就是"递"的过程, 空指针跳过while (root)循环和指针出栈就是"归"的过程