二叉树 || 三种遍历的非递归实现

2019-10-12  本文已影响0人  zilla

思路

无论是前序、中序、后序,遍历二叉树的过程都是基本一致的。
不失一般性,把叶结点的左右子树看成空树。空树没有孩子,到空树返回。
那么对某结点的遍历过程可描述为:

任意一个非空结点都路过了三次
前序:第一次路过时访问。
中序:第二次路过时访问。
后序:第三次路过时访问。

为了能回到之前路过的结点,需要把它存下来,用栈!
因此,可以每个结点增设一个计数已经路过次数的量来实现非递归的遍历是可行的。

参考

实现

// non-recursive
void in_traverse(Node* root) {
    stack<Node*> ms;
    Node* p = root;
    while(p || !ms.empty()) {
        if(p) {
            ms.push(p);
            p = p->lc;
        } else {
            p = ms.top();
            printf("%d ", p->val);
            ms.pop();
            p = p->rc;
        }
    }
}

相比中序的非递归版,只改变了访问结点的时机。

void pre_traverse(Node* root) {
    stack<Node*> ms;
    Node* p = root;
    while(p || !ms.empty()) {
        if(p) {
            printf("%d ", p->val);
            ms.push(p);
            p = p->lc;
        } else {
            p = ms.top();
            ms.pop();
            p = p->rc;
        }
    }
}

post_traverse(root);
想办法把 "访问完右子树再访问根结点" 表达出来
关键是确定刚访问过的结点位于当前结点的左子树还是右子树

上一篇下一篇

猜你喜欢

热点阅读