二叉树的迭代法遍历、统一迭代法遍历

二叉树的迭代法遍历、统一迭代法遍历,第1张

144. 二叉树的前序遍历

采用迭代的方式进行实现 。


递归时使用栈存储临时变量和参数,因此也可以使用栈来实现二叉树的遍历。


前序遍历是中左右,因而入栈顺序应该是先右后左,出栈即为左右。


每次取出栈顶元素,放入结果中,再将栈顶元素的右、左分别压栈即可。


代码实现:

class Solution {
public:
    vector preorderTraversal(TreeNode* root) {
        vectorresult;
        stack s;
        if(root == NULL)
            return result;
        s.push(root);
        while(!s.empty()){
            TreeNode* cur = s.top();
            s.pop();
            result.push_back(cur->val);
            if (cur->right)//空节点不入栈
                s.push(cur->right);
            if (cur->left)
                s.push(cur->left);
        }
        return result;
    }
};

94. 二叉树的中序遍历

可能一上来想按照和前序遍历一样的解法来写,但是此处并不行。


前面的迭代过程中,其实有两个 *** 作:

(1)处理节点:将元素push_back放入result中

(2)访问元素

在前序遍历时要访问的元素和要处理的元素顺序是一致的,都是中间节点。


但是中序遍历并不一致,中序遍历先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。


先访问后处理,因此此时使用一个栈存储将要处理的元素,使用一个指针进行访问。


首先访问至最底层(指针指向NULL),然后出栈,处理元素,再访问其右侧节点。


代码实现:

class Solution {
public:
    vector inorderTraversal(TreeNode* root) {
        vectorresult;
        stackst;
        if(root == NULL)
            return result;
        TreeNode* p = root;
        while(p != NULL || !st.empty()){
            if (p == NULL){//p访问至最底层,再进行处理(最底层时没有左节点,只剩下了中右)
                p = st.top();
                st.pop();
                result.push_back(p->val);//中
                p = p->right;//右
                    
            }
            else{
                st.push(p);
                p = p->left;
            }
        }
        return result;
    }
};

145. 二叉树的后序遍历

二叉树后序遍历的顺序为左右中,前序遍历为中左右,只需要将前序遍历修改为中右左,再对结果进行反转即为后序遍历的结果左右中。


 

代码实现:

class Solution {
public:
    
    vector postorderTraversal(TreeNode* root) {
        vector result;
        stackst;
        if (root == NULL)
            return result;
        st.push(root);
        while(!st.empty()){
            TreeNode* p = st.top();
            st.pop();
            result.push_back(p->val);//中
            if (p->left)//先压左再压右,出栈是为右左
                st.push(p->left);
            if (p->right)
                st.push(p->right);
        }
        reverse(result.begin(), result.end());//中右左反过来即为中左右
        return result;
    }
};

二叉树的统一迭代法:

前面前序遍历和后序遍历稍加修改即可实现,但是中序遍历由于访问和处理的顺序不一致,无法稍加修改实现。


那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。


如何标记,就是在要处理的节点放入栈之后,紧接着放入一个空指针作为标记。


 这种方法也可以叫做标记法。


统一迭代中序遍历如下:(代码来自carl)

class Solution {
public:
    vector inorderTraversal(TreeNode* root) {
        vector result;
        stack st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop(); // 将该节点d出,避免重复 *** 作,下面再将右中左节点添加到栈中
                if (node->right) st.push(node->right);  // 添加右节点(空节点不入栈)

                st.push(node);                          // 添加中节点
                st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。


if (node->left) st.push(node->left); // 添加左节点(空节点不入栈) } else { // 只有遇到空节点的时候,才将下一个节点放进结果集 st.pop(); // 将空节点d出 node = st.top(); // 重新取出栈中元素 st.pop(); result.push_back(node->val); // 加入到结果集 } } return result; } };

 前序遍历时只需将中间部分改为:

if (node->right) st.push(node->right);  // 右
if (node->left) st.push(node->left);    // 左
st.push(node);                          // 中
st.push(NULL);

后序遍历时:

st.push(node);                          // 中
st.push(NULL);

if (node->right) st.push(node->right);  // 右
if (node->left) st.push(node->left);    // 左

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/621725.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-15
下一篇 2022-04-15

发表评论

登录后才能评论

评论列表(0条)

保存