二叉树的先序、中序和后序遍历(总结)

废话不多说,分别给出二叉树的先序、中序和后序遍历的递归和非递归算法。
先序遍历-递归算法:

class Node {
public:
    int value;
    Node *left;
    Node *right;
};

class Visit {
public:
    void operator() (Node * node) const {
        cout<<" "<<node->value<<" "<<endl;
    }
};

void preOrderVisitTree(Node* root, Visit &visit) {
    if (!root) {
        return ;
    }
    visit(root);
    preOrderVisitTree(root->left,visit);
    preOrderVisitTree(root->right,visit);
    return ;
}

先序遍历-非递归算法:
思想:用一个辅助栈记录,比较简单这里就不废话了。
No code say what?

void preOrderVisitTreeEx(Node *root, Visit &visit) {
    if (!root) {
        return ;
    }

    stack<Node*> S;
    Node *current = root;
    while (!S.empty()) {
        if (current->right) {
            S.push(current->left);
        }
        if (current->left) {
            S.push(current->right);
        }

        visit(current);
        current = S.top();
        S.pop();
    }

    return;
}

中序遍历-递归算法:

void inOrderVisitTree(Node* root, Visit &visit) {
    if (!root) {
        return ;
    }

    preOrderVisitTree(root->left,visit);
    visit(root);
    preOrderVisitTree(root->right,visit);
    return ;
}

中序遍历-非递归算法:
思想:一直把树的左边界压入栈,当压无可压时,弹出一个节点,然后访问其右子树。再一直压树的左边界…
No code say what?

void inOrderVisitTreeEx(Node *root, Visit & visit) {
    if (!root) {
        return ;
    }

    stack<Node*> S;
    Node *current = root;
    while (!S.empty() && !current) {
        if (current->left) {
            S.push(current->left);
            current = current->left;
            continue;
        }
        current = S.top();
        S.pop();
        visit(current);
        current = current->right;
    }

    return ;
}

后序遍历-递归算法:

void posOrderVisitTree(Node* root, Visit &visit) {
    if (!root) {
        return ;
    }

    preOrderVisitTree(root->left,visit);
    preOrderVisitTree(root->right,visit);
    visit(root);
    return ;
}

后序遍历-非递归法
思想:后序遍历非递归算法稍微复杂点,下面给出了两种方法,这里说几句。
methold1:把后序顺序的节点序导入到一个栈中,然后依次遍历这个栈。有两个栈就很容易搞定这个事,假设最后待遍历的栈为Stack2,另一个栈为Stack1,首先入栈root到stack1,stack1弹出节点A,节点A并压入stack2,把A的左右儿子压入stack1,以此循环一直到stack1空为止。此时以此弹出stack2就可得到树的后序遍历序列。
No code say what?

void posOrderVisitTreeEx(Node* root, Visit &visit) {
    if (!root) {
        return ;
    }

    stack<Node*> S1;
    stack<Node*> S2;
    Node *current = NULL;
    S1.push(root);
    while (!S1.empty() &&current) {
        current = S1.top();
        S1.pop();
        S2.push(current);
        if (current->left) {
            S1.push(current->left);
        }
        if (current->right) {
            S1.push(current->right);
        }

    }

    while (!S2.empty()) {
        visit(S2.top());
        S2.pop();
    }

    return ;
}

methold2:
不用两个栈,用一个栈,这个思路比较绕。
1.首先把头节点入栈;
2.然后获得当前栈顶元素(不弹出);
3.判断栈顶元素左子树是否为空,
若不为空,且其左右子树都未访问过,就把此节点左子树头节点入栈;
4.判断栈顶元素右子树是否为空,
若不为空,且其右子树未被访问过,就把此节点的右子树头节点入栈。
No code say what?

void posOrderVisitTreeExt(Node* root, Visit &visit) {
    if (!root) {
        return ;
    }

    stack<Node*> S;
    Node *h = NULL;
    Node *c = NULL;
    S.push(root);
    while (!S.empty()) {
        c = S.top();
        if (!c->left && c->left != h && c->right != h) {
            S.push(c->left);
        } else if (!c->right && c->right != h) {
            S.push(c->right);
        } else {
            visit(h);
            h = c;
        }
    }

    return ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值