1.前序与中序遍框架流程图
前序与中序遍历框架大体一致,后序稍有不同。具体流程图如下:
实现逻辑可参考leetCode:
leetCode:迭代与递归两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同。
前序遍历:二叉树的前序遍历 - 二叉树的前序遍历 - 力扣(LeetCode) (leetcode-cn.com)
中序遍历:二叉树的中序遍历 - 二叉树的中序遍历 - 力扣(LeetCode) (leetcode-cn.com)
后序遍历:二叉树的后序遍历 - 二叉树的后序遍历 - 力扣(LeetCode) (leetcode-cn.com)
2.C++实现前中后序遍历
二叉树结构与递归实现参考:(25条消息) 二叉树的实现与递归遍历_Foplp的博客-CSDN博客https://blog.csdn.net/Foplp/article/details/121508986?spm=1001.2014.3001.5501
/**
* @brief (迭代)先序遍历二叉树
* @param root 二叉树根节点
*/
void preOrderTraverseIteration(const TreeNodePtr& root);
/**
* @brief (迭代)中序遍历二叉树
* @param root 二叉树根节点
*/
void inOrderTraverseIteration(const TreeNodePtr& root);
/**
* @brief (迭代)后序遍历二叉树
* @param root 二叉树根节点
*/
void postOrderTraverseIteration(const TreeNodePtr& root);
void BinaryTree::preOrderTraverseIteration(const TreeNodePtr& root)
{
//迭代与递归其实一样,只不过把递归隐式维护的栈显式维护
stack<TreeNodePtr> stk;
//当前节点为二叉树根节点
TreeNodePtr node = root;
//栈空了并且当前节点为空(没有子树)说明全部遍历完毕了
while (!stk.empty() || node )
{
//当节点不为空时找到最左子树
while (node != nullptr) {
//根据先序遍历规则先显示根节点
disPlayBiTree(node);
//当前根节点压入栈
stk.emplace(node);
//寻找其左子树
node = node->left;
}
//当前节点左孩子为空,说明其实最左子树,让当前节点指向栈顶(当前未遍历最左子树)
node = stk.top();
stk.pop();
//修正当前节点为其右孩子
node = node->right;
}
}
void BinaryTree::inOrderTraverseIteration(const TreeNodePtr & root)
{
stack<TreeNodePtr> stk;
TreeNodePtr node = root;
while (!stk.empty() || node )
{
while (node!=nullptr)
{
stk.emplace(node);
node = node->left;
}
node = stk.top();
disPlayBiTree(node);
stk.pop();
node = node->right;
}
}
void BinaryTree::postOrderTraverseIteration(const TreeNodePtr & root)
{
stack<TreeNodePtr> stk;
TreeNodePtr prev = nullptr;
TreeNodePtr node = root;
while (node != nullptr || !stk.empty()) {
//寻找最左子节点
while (node != nullptr) {
stk.emplace(node);
node = node->left;
}
//当前节点为最左子节点
node = stk.top();
stk.pop();
//该节点没有右子树或右子树已经遍历过
if (!node->right || node->right == prev)
{
disPlayBiTree(node);
//表示当前节点已经遍历过
prev = node;
node = nullptr;
}
//当前节点有右子树,找到最右子树
else {
stk.emplace(node);
node = node->right;
}
}
}