迭代本质上是在利用栈的辅助模拟递归,搞清迭代事实上就是搞清计算机到底做了什么,以及在整个二叉树中数据的走向。因此我们的思路也可以顺着递归的路线,一步一步走。
前序
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;
}
};
中序
刚刚在迭代的过程中,其实我们有两个操作:
- 处理:将元素放进result数组中
- 访问:遍历节点
分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。
那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进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;
}
};