二叉树:标记法,让前中后序的迭代方法统一起来

二叉树:标记法,让前中后序的迭代方法统一起来

迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,那是因为处理顺序和访问顺序是不一致的。前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。

详解在代码注释里:

1.中序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    
    
public:
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        if(root != nullptr)
        st.push(root);
        while(!st.empty())
        {
    
    
            TreeNode* node = st.top();
            if(node != NULL)
            {
    
    
                st.pop();//出栈,防止死循环
                if(node->right)
                st.push(node->right);//添加右节点

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

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

2. 前序遍历

注意此时我们和中序遍历相比仅仅改变了两行代码的顺序

class Solution {
    
    
public:
    vector<int> preorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
    
    
            TreeNode* node = st.top();
            if (node != NULL) {
    
    
                st.pop();
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左
                st.push(node);                          // 中
                st.push(NULL);
            } else {
    
    
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

3.后序遍历

注意此时我们和中序遍历相比仅仅改变了两行代码的顺序

class Solution {
    
    
public:
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
    
    
            TreeNode* node = st.top();
            if (node != NULL) {
    
    
                st.pop();
                st.push(node);                          // 中
                st.push(NULL);

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

            } else {
    
    
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

总结

射射兄弟,有被爽到!

猜你喜欢

转载自blog.csdn.net/cckluv/article/details/112751677