二叉树的前中后序遍历

参考了一些别人的博客和评论,整理出来的:http://blog.youkuaiyun.com/fansongy/article/details/6798278/

值得强调的一点是,在出栈操作后,对弹出指针指向的结点(一般是父结点),尽量采用直接操作的方式,关键在于要避免下次循环进来时,指针仍指向该弹出的结点,容易造成重复访问。

树的结点结构如下:

struct TreeNode{
    int val;
    TreeNode* leftkid;
    TreeNode* rightkid;
    TreeNode() :val(0), leftkid(NULL), rightkid(NULL) {};
};

前序遍历:

void PreOrderTraverse(TreeNode* root) {
    stack<TreeNode*> Tstack;
    TreeNode* p = root;

    while (p || !Tstack.empty()) {
        while (p)   {
            cout << p->val << " ";
            Tstack.push(p);
            p = p->leftkid;
        }
        p = Tstack.top()->rightkid;
        Tstack.pop();
    }
    return;
}

中序遍历:

void MidOrderTraverse(TreeNode* root) {
    stack<TreeNode*> Tstack;
    TreeNode* p = root;
    while (p || !Tstack.empty()) {
        while (p)   {
            Tstack.push(p);
            p = p->leftkid;
        }
        cout << Tstack.top()->val << " ";
        p = Tstack.top()->rightkid;
        Tstack.pop();
    }
    return;
}

后续遍历:

void PostOrderTraverse(TreeNode* root) {
    stack<TreeNode*> Tstack;
    TreeNode* p = root;

    while (true) {
        while (p)   {
            Tstack.push(p);
            p = p->leftkid;
        }
        while (!Tstack.empty() && p == Tstack.top()->rightkid) {
            p = Tstack.top();
            cout << p->val << " ";
            Tstack.pop();
        }
        if (Tstack.empty()) break;
        p = Tstack.top()->rightkid;
    }
    return;
}

对出栈操作的部分,由于出栈的结点都是之前访问过的,所以不需要(应该说要避免)再次去访问它的子节点。那么对它来说只有两种需要考虑的情况:作为其父节点的左子节点或者右子节点。如果是左子节点,那么接下来要访问其兄弟节点;如果是右子节点,则说明其父节点的所有子节点已访问完毕,这时应访问父节点。

后序遍历还可以这样实现:
把先序遍历的代码中的left全换为right,right全换为left,最后就得到了后序遍历的逆序,反向输出就是后序遍历的顺序了。
【但是不建议用这种方式,很多面试笔试目的在于考察对树结构的理解以及栈的操作。此外,某些情况下,结点内可能保存着重要的拓扑结构,改变访问顺序对结点影响很大】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值