一、回顾递归法
每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归发各项参数,所以这就是为什么递归可以返回上一层位置的原因,即用栈也可以实现二叉树的前中后序遍历。
二、中序迭代遍历的特殊性
前【右根左】后序的代码不能和中序迭代遍历通用,后序可以根据前序修改【根右左=>最后反转】,因为前序遍历的顺序是根左右,先访问的元素是根节点,要处理的元素也是根节点,即要访问的元素和要处理的元素顺序是一致的。但中序遍历是左根右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点,即要访问的顺序和处理的不一致。
三、迭代方法1
思路:借助指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
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;
}
四、迭代方法2【统一:前后序可以在此基础上修改】
思路:把将访问的节点放入栈,把要处理的节点也放入栈但要做标记【要处理的节点放入栈后,加入一个空指针做标记】
vector<int> inorderTraversal(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); //右
st.push(node); //根
st.push(NULL); //做标记
if(node->left) st.push(node->left); //左
} else {
st.pop(); //弹出NULL
node = st.top();
st.pop();
result.push_back(node->val); //处理
}
}
return result;
}