zoukankan      html  css  js  c++  java
  • 二叉树非递归前序、中序、后序遍历

    1.二叉树前序遍历:

    节点定义:

    //Definition for a binary tree node.
    struct TreeNode
    {
        int val;
        TreeNode *left;
        TreeNode *right;
        TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    };

    Leetcode144: https://leetcode.com/problems/binary-tree-preorder-traversal/

    class Solution
    {
    public:
        vector<int> preorderTraversal(TreeNode* root)
        {
            vector<int> res;
            stack<TreeNode*> right_nodes;
            if(root!=nullptr)
                right_nodes.push(root);
            while(!right_nodes.empty())
            {
                TreeNode* node=right_nodes.top();
                right_nodes.pop();
                res.push_back(node->val);
                if(node->right!=nullptr)
                    right_nodes.push(node->right);
                TreeNode* left_son=node->left;
                while(left_son!=nullptr)
                {
                    res.push_back(left_son->val);
                    if(left_son->right!=nullptr)
                        right_nodes.push(left_son->right);
                    left_son=left_son->left;
                }
            }
            return res;
        }
    };

    2.二叉树中序遍历:

    Leetcode94: https://leetcode.com/problems/binary-tree-inorder-traversal/

    基本思路:

    1.将根节点压栈,并从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈。

    2.取栈顶节点,必定已访问过其左节点,输出val,并出栈;

    3.若该节点有右孩子,则对右孩子做根节点一样的操作,即将右孩子压栈,并从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈。

    4.返回第2步,直至栈空。

    class Solution
    {
    public:
        vector<int> inorderTraversal(TreeNode* root)
        {
            stack<TreeNode*> nodes;
            vector<int> res;
            if(root!=nullptr) //根节点非空
            {
                //将根节点压栈,并一直遍历到二叉树最左下
                nodes.push(root); 
                if(root->left!=nullptr)
                {
                    TreeNode* left=root->left;
                    while(left!=nullptr)
                    {
                        nodes.push(left);
                        left=left->left;
                    }
                }
            }
            while(!nodes.empty())
            {
                //对于出栈节点,已访问过其左孩子
                TreeNode* node=nodes.top();
                nodes.pop();
                res.push_back(node->val);
                //若该节点右孩子非空
                if(node->right!=nullptr)
                {
                    //右孩子压栈
                    TreeNode* right=node->right;
                    nodes.push(right);
                    //该节点左孩子非空,延该节点走到最左下
                    if(right->left!=nullptr)
                    {
                        TreeNode* left=right->left;
                        while(left!=nullptr)
                        {
                            nodes.push(left);
                            left=left->left;
                        }
                    }
                }
            }
            return res;
        }
    };

    3.二叉树后序遍历:

    Leetcode145: https://leetcode.com/problems/binary-tree-postorder-traversal/

    后序遍历除了需要一个辅助栈,还需要给每一个栈中元素一个标记,标记这个节点是否已访问过其左节点和是否已访问过其左右节点。

    基本思路:

    1.若根节点非空,将其压栈。

    2.取栈顶节点

    a. 若标记visited==0,说明未访问过该节点的孩子;从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈,并将压栈节点的标记都置为1(因为访问过其左孩子了)。

    b. 若标记visited==1,说明访问过其左孩子,将其右孩子压栈,并将该节点标记置为2,从该节点一直走到最左下(一直沿着左孩子走到左孩子非空的节点),途中依次将经过的节点压栈,并将压栈节点的标记都置为1。

    c. 若标记visited==2,说明访问过其左右孩子,则直接输出其val。

    3.返回至第2步,直至栈空。

    class Solution
    {
    public:
        vector<int> postorderTraversal(TreeNode* root)
        {
            vector<int> res;
            map<TreeNode*, int> visited;
            stack<TreeNode*> nodes;
            if(root!=nullptr)
                nodes.push(root);
            while(!nodes.empty())
            {
                TreeNode* node=nodes.top();
                if(visited.count(node))
                {
                    if(visited[node]==2)
                    {
                        //cout<<node->val<<endl;
                        res.push_back(node->val);
                        nodes.pop();
                    }
                    else ///visit right son
                    {
                        visited[node]=2;
                        if(node->right!=nullptr)
                        {
                            TreeNode* right=node->right;
                            visited[right]=1;
                            nodes.push(right);
                            TreeNode* left=right->left;
                            while(left!=nullptr)
                            {
                                visited[left]=1;
                                nodes.push(left);
                                left=left->left;
                            }
                        }
                    }
                }
                else
                {
                    TreeNode* left=node->left;
                    visited[node]=1;
                    while(left!=nullptr)
                    {
                        visited[left]=1;
                        nodes.push(left);
                        left=left->left;
                    }
                }
            }
            return res;
        }
    };
  • 相关阅读:
    第一次用NUnitAsp
    IT能够解决所有的商业问题吗?
    在这种东西里面,你会自在吗?
    看了段.net show之后的感想
    获取当前数据库中所有表的记录数
    对瀑布模型各阶段的解释
    Linux内核中的slab/slob/slub 在搞晕前先记下来
    分布式事务AT、TCC、Saga、XA 模式分析对比
    读懂Windows的“虚拟内存”为你量身定制
    示范NTFS 卷上的硬链接
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/11149557.html
Copyright © 2011-2022 走看看