一、前序遍历非递归
力扣链接:力扣第144题:前序遍历
解析:
我们的思路是这样的:递归的本质其实就是一层一层的栈帧。我们要使用非递归,就得模拟这种栈帧,所以我们需要一个栈。这个栈专门存储结点,我们可以定义一个cur指针,先让他指向root。由于是先序遍历,所以我们需要将cur的所有左树结点都直接存入栈里面,并且我们还要顺便将里面的值给放入数组中,然后接下来我们就取出栈顶的结点,然后让cur指向右子树即可。这样循环下去就可以了
/** * 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> v; stack<TreeNode*> st; TreeNode* cur = root; while(cur || !st.empty()) { while(cur) { v.push_back(cur->val); st.push(cur); cur = cur->left; } TreeNode* top =st.top(); st.pop(); cur = top->right; } return v; } };
除了上面的方式以外,由于是先序遍历,所以可以先访问根节点,然后先访问右子树,然后访问左子树,依次放入栈里面,不过这种方法并不适合中序与后序。因为会陷入死循环。
/** * 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) { if(root == nullptr) { return {}; } vector<int> v; stack<TreeNode*> st; st.push(root); while(!st.empty()) { TreeNode* top = st.top(); v.push_back(top->val); st.pop(); if(top->right) { st.push(top->right); } if(top->left) { st.push(top->left); } } return v; } };
二、中序遍历非递归
力扣链接:力扣第94题:二叉树的中序遍历
解析:
这道题与前序遍历是非常相似的,只需要改变结点进入顺序表的时机即可。
/** * 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> v; stack<TreeNode*> st; TreeNode* cur = root; while(cur||!st.empty()) { while(cur) { st.push(cur); cur = cur->left; } TreeNode* top = st.top(); st.pop(); v.push_back(top->val); cur = top->right; } return v; } };
三、后序遍历非递归
力扣链接:力扣第145题:二叉树的后序遍历
解析:
这道题的麻烦之处,在于如何区分访问根节点还是往右子树走。
我们可以设置一个变量记录之前访问的右子树结点。
如果我们现在要访问的结点,它的右子树正好访问过,那么说明这个结点已经到了访问根节点的地步。
如果当前访问的右子树为空,说明已经到头了,需要访问这个结点了。
如果都不满足,那么就说明还需要继续访问右子树才可以。
/** * 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> v; stack<TreeNode*> st; TreeNode* cur = root; TreeNode* prev = nullptr; while(cur||!st.empty()) { while(cur) { st.push(cur); cur = cur->left; } TreeNode* top = st.top(); if(top->right == nullptr||top->right == prev) { prev = top; v.push_back(top->val); st.pop(); } else { cur = top->right; } } return v; } };