递归遍历二叉树
#include <iostream>
#include <stack>
using namespace std;
struct tree
{
int val;
tree * left;
tree * right;
};
//前序遍历
void RecursivePreTraverse(tree * root)
{
//指明递归终止条件
if (!root)
return;
printf("%d ", root->val);
RecursivePreTraverse(root->left);
RecursivePreTraverse(root->right);
}
//中序遍历
void RecursiveInterTraverse(tree * root)
{
//指明递归终止条件
if (!root)
return;
RecursiveInterTraverse(root->left);
printf("%d ", root->val);
RecursiveInterTraverse(root->right);
}
//后序遍历
void RecursivePostTraverse(tree * root)
{
//指明递归终止条件
if (!root)
return;
RecursivePostTraverse(root->left);
RecursivePostTraverse(root->right);
printf("%d ", root->val);
}
非递归后序遍历二叉树
#include <iostream>
#include <stack>
using namespace std;
struct tree
{
int val;
tree * left;
tree * right;
};
void nonRecursivePostTraverse(tree * root)
{
if (root == nullptr)
return;
stack<tree*>s;
tree * last=nullptr; //last记录的是上一个出栈的元素(对应后序遍历而言,每一个出栈的元素都代表其左右子树都已处理完毕)
//1 将从根节点开始的所有非空左子节点都入栈
while (root != nullptr)
{
s.push(root);
root = root->left;
}
//2 在栈不为空的大前提下,查看栈顶元素,获取该元素的右子节点。如果右子节点为不空,重复1
while (!s.empty())
{
tree* top = s.top();
//后序遍历和前序、中序遍历的出栈时机不同,前、中是处理完左子树即可出栈,后是必须左右子树都处理完才能出栈
//后序遍历,元素出栈的要求必须是左右子树都已经处理完毕,有三种情况
//1 该节点的左子树、右子树均为空,都不需要处理,可以直接输出根节点
//2 上一个出栈的元素(即左右子树已经处理完毕的元素)是该节点的右子节点,因为左节点处理在右节点之前,所以意味着当前节点的左右子树都已经处理完毕,可以直接输出
//3 上一个出栈的元素是该节点的左子节点且右子节点为空时,说明当前节点的左子树已经处理完毕,右子树为空不需要处理,可以直接输出
if (top->left == nullptr && top->right == nullptr
|| last == top->right
|| last == top->left && top->right == nullptr)
{
//后序遍历打印元素也是在元素出栈时
printf("%d ",top->val);
//判定符合出栈条件后,记得更新前一个出栈元素last
last = top;
s.pop();
}
else
{
//不满足出栈条件(即左右子树还未处理完毕),栈顶元素不出栈,获取其右子节点,重复1
tree *t = top->right;
while (t)
{
s.push(t);
t = t->left;
}
}
}
}
非递归前序遍历二叉树
#include <iostream>
#include <stack>
using namespace std;
struct tree
{
int val;
tree * left;
tree * right;
};
void nonRecursivePreTraverse(tree * root)
{
if (root == nullptr)
return;
stack<tree*>s;
//1 将从根节点开始的所有非空左子节点都入栈
while (root)
{
//前序遍历是在元素入栈前打印
printf("%d ", root->val);
s.push(root);
root = root->left;
}
//2 在栈不为空的大前提下,查看栈顶元素,获取该元素的右子节点,将该元素出栈。如果右子节点为不空,重复1
while (!s.empty())
{
tree* top = s.top();
tree *t = top->right;
s.pop();
while (t)
{
//前序遍历是在元素入栈前打印
printf("%d ", root->val);
s.push(t);
t = t->left;
}
}
}
非递归中序遍历二叉树
#include <iostream>
#include <stack>
using namespace std;
struct tree
{
int val;
tree * left;
tree * right;
};
void nonRecursiveInterTraverse(tree * root)
{
if (root == nullptr)
return;
stack<tree*>s;
//1 将从根节点开始的所有非空左子节点都入栈
while (root)
{
s.push(root);
root = root->left;
}
//2 在栈不为空的大前提下,查看栈顶元素,获取该元素的右子节点,将该元素出栈。如果右子节点为不空,重复1
while (!s.empty())
{
tree* top = s.top();
//中序遍历是在元素弹出时打印
printf("%d ", top->val);
tree *t = top->right;
s.pop();
while (t)
{
s.push(t);
t = t->left;
}
}
}