【无标题】

二叉树的非递归遍历-迭代


迭代本质上是在利用栈的辅助模拟递归,搞清迭代事实上就是搞清计算机到底做了什么,以及在整个二叉树中数据的走向。因此我们的思路也可以顺着递归的路线,一步一步走。

前序

144. 二叉树的前序遍历
思路: 由于“中左右”的访问顺序正好符合根结点寻找子节点的顺序,因此每次循环时弹栈,输出此弹栈结点并将其右结点和左结点按照叙述顺序依次入栈。至于为什么要右结点先入栈,是因为栈后进先出的特性。右结点先入栈,就会后输出右结点。 初始化: 一开始让root结点先入栈,满足循环条件
步骤:
弹栈栈顶元素,同时输出此结点
当前结点的右结点入栈
当前结点的左结点入栈
重复上述过程 结束条件: 每次弹栈根结点后入栈子结点,栈为空时则说明遍历结束。

/**
 * 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> preorderTraversal(TreeNode* root) {
       vector <int> result;//定义一个数组存储结果
       stack <TreeNode*> st;
       if(root==NULL)  return result;
       st.push(root);
       while(!st.empty())
       {
           TreeNode* node=st.top();
           st.pop();
           result.push_back(node->val);
           if(node->right) st.push(node->right);//右
           if(node->left)  st.push(node->left);//左
       }
       return result;      
    }
};

后序

/**
 * 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> postorderTraversal(TreeNode* root) {
        vector <int> result;//定义一个数组存储结果
       stack <TreeNode*> st;
       if(root==NULL)  return result;
       st.push(root);
       while(!st.empty())
       {
           TreeNode* node=st.top();
           st.pop();
           result.push_back(node->val);
           
           if(node->left)  st.push(node->left);//左
           if(node->right) st.push(node->right);//右
       }
       reverse(result.begin(),result.end());
       return result;
        

    }
};

中序

刚刚在迭代的过程中,其实我们有两个操作:

  1. 处理:将元素放进result数组中
  2. 访问:遍历节点

分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。

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

那么在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。

/**
 * 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;
        TreeNode *cur=root;
        while(cur!=NULL||!st.empty())
        {
            if(cur!=NULL)
            {
                st.push(cur);
                cur = cur->left;
            }
            else
            {
                cur=st.top();
                st.pop();
                result.push_back(cur->val);
                cur=cur->right;
            }
        }
        return result;
    }
    
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值