## 二叉树的遍历需要把当前根节点和左右子树抽象成只有一个根节点和一个左子树,一个右子树的情况
##套路 二叉树的遍历先序中序后序无非是根节点的处理顺序不同,三种遍历方式都有一个相同的逻辑流程,不管怎么样首先将左子树入栈,遍历无非是处理的时机不一样。
1. 先序遍历 根节点的处理顺序和进栈的顺序一致,即进栈并且处理根节点
2. 中序遍历 左节点处理完成之后处理根节点,在程序中就是出栈之后处理根节点
3. 后序遍历(与先序和中序不同)
栈顶的元素是否处理需要满足条件,出栈入栈的顺序不能简单的和处理根节点的顺序一致,需要记住最近依次处理的结点,
满足条件 1. 栈顶元素的右子树为空 2. 栈顶元素的右子树被处理过
先序和中序代码基本一致:
void search_order(BTNode* node)
{
QStack<BTNode*> stack_;
BTNode* curNode = node;
if (node)
// 不管三七二十一 左子树直接入栈
{
while (curNode)
{
//printf(" %c", curNode->data.toLatin1()); // 进栈之前处理先序
stack_.push_back(curNode);
curNode = curNode->lchild;
}
while (!stack_.empty())
{
curNode = stack_.top(); // 出栈即表示栈顶元素的左子树已经处理完毕
stack_.pop();
//printf(" %c", curNode->data.toLatin1()); // 出栈之后处理 中序
curNode = curNode->rchild;
while (curNode)
{
//printf(" %c ", curNode->data.toLatin1()); // 进栈之前处理先序
stack_.push(curNode);
curNode = curNode->lchild;
}
}
printf("\n");
}
}
后续遍历:
void Postorder(BTNode* node)
{
QStack<BTNode*> stack_;
BTNode* curNode = node;
BTNode* lastNode = nullptr;
if (curNode)
{
while (curNode)
{
stack_.push(curNode);
curNode = curNode->lchild;
}
while (!stack_.empty()) {
curNode = stack_.top();
// 当前结点需要出栈的条件
//① 已访问的结点为当前结点的右节点
// ② 当前结点为叶子结点
// ③ 已访问的结点为栈顶元素的左节点 并且有栈顶元素的叶节点为空
// 以上三个添加可以合并 栈顶元素的右子树为空,或者栈顶元素的右节点为已访问的结点
/*if ( (!curNode->lchild && !curNode->rchild)
|| (curNode->rchild == lastNode)
|| (curNode->lchild == lastNode && curNode->rchild == NULL))*/
if( curNode->rchild == NULL || curNode->rchild == lastNode)
{
printf(" %c ", curNode->data.toLatin1());
lastNode = curNode;
stack_.pop();
}
else
{
curNode = curNode->rchild;
while (curNode)
{
stack_.push(curNode);
curNode = curNode->lchild;
}
}
}
}
}