二叉树的非递归遍历

#include <iostream>
#include <string>
#include <stack>

using namespace std;

typedef struct BTNode
{
    char data;
    BTNode *lChild;
    BTNode *rChild;
} BTNode, *BTree;

BTree create_tree();
void pre_traverse(BTree);
void in_traverse(BTree);
void post_traverse(BTree);

int main()
{
    BTree head = create_tree();
    // pre_traverse(head);
    // in_traverse(head);
    post_traverse(head);

    return 0;
}

BTree create_tree()
{
    //容易出错的地方是没有左右子树的节点要显示置空
    //不然很容易出现野指针的问题,递归会死循环

    BTree head = new BTNode;
    head->data = 'A';

    BTree b = new BTNode;
    b->data = 'B';
    head->lChild = b;

    BTree c = new BTNode;
    c->data = 'C';
    head->rChild = c;

    c->lChild = nullptr;
    c->rChild = nullptr;

    BTree d = new BTNode;
    d->data = 'D';
    b->lChild = d;

    d->lChild = nullptr;
    d->rChild = nullptr;

    BTree f = new BTNode;
    f->data = 'F';
    b->rChild = f;

    f->lChild = nullptr;
    f->rChild = nullptr;

    return head;
}

void pre_traverse(BTree head)
{
    stack<BTNode> stack; //创建一个空栈
    //因为BTree是指针类型的,最好是定义的时候就初始化,不然容易出现野指针
    BTree pop_node = nullptr; //用来保存出栈的结点
    BTree cur_node = head;    //定义用来指向当前访问节点的指针

    while (cur_node || stack.empty() == false)
    {
        //从根节点开始,输出当前结点,并将其入栈
        //同时转向左孩子为当前节点,直至左孩子没有没有左孩子
        cout << cur_node->data << "\t";
        stack.push(*cur_node); //当前结点入栈
        cur_node = cur_node->lChild;

        //如果当前结点为空,且栈不空,则将栈顶结点出栈
        //转向右子树为当前结点,循环判断,知道cur_node为空
        while (cur_node == nullptr && stack.empty() == false)
        {
            cur_node = &stack.top(); //取栈顶元素
            stack.pop();
            cur_node = cur_node->rChild;
        }
    }
}

void in_traverse(BTree head)
{
    stack<BTNode *> stack; //初始化一个空栈

    BTNode *cur_node = head;

    while (cur_node || !stack.empty())
    {
        stack.push(cur_node);
        cur_node = cur_node->lChild;

        //左子树走到叶子结点了,然后访问跟结点,然后转向右子树
        while (!cur_node && !stack.empty())
        {
            cur_node = stack.top(); //左子树为空的结点
            stack.pop();
            cout << cur_node->data << "\t"; //访问结点

            cur_node = cur_node->rChild; //转向右子树
        }
    }
}

void post_traverse(BTree head)
{
    stack<BTNode *> stack;
    BTNode *cur_node = head;
    BTNode *pre_node = nullptr;

    stack.push(cur_node);
    while (!stack.empty())
    {
        cur_node = stack.top();
        //沿着左子树一直遍历,直到找到一个左子树为空的结点
        if ((cur_node->lChild == nullptr && cur_node->rChild == nullptr) || //左右子树都空,那么可以直接输出当前结点
                                                                            //前一个结点不为空,如果前一个结点是当前结点的左结点,说明当前结点只有左孩子,且已经访问过,可以输出当前结点
                                                                            //前一个结点不为空,如果前一个结点时当前结点的右孩子,说明当前结点有左右子树,且右子树也被访问,可以输出当前结点
            (pre_node != nullptr && (cur_node->lChild == pre_node || cur_node->rChild == pre_node)))
        {
            cout << cur_node->data << "\t";
            stack.pop();
            pre_node = cur_node;
        }
        else
        {
            //如果不满足上足情况,将其右孩子,左孩子依次入栈
            if (cur_node->rChild)
            {
                stack.push(cur_node->rChild);
            }
            if (cur_node->lChild)
            {
                stack.push(cur_node->lChild);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值