递归的实现就是每一次递归调用都把函数的局部变量、参数值和返回地址压入栈中,然后递归返回时弹出上次递归调用的各项参数,这就是递归为什么可以返回上一层位置的原因,所以可以用栈实现二叉树的遍历。
1.前序遍历
前序遍历需要处理根结点,然后将右节点加入栈,再加入左结点。
每出栈一个结点,就加入它的右孩子和左孩子。
//前序遍历
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
st.push(root);
while(! st.empty()) {
TreeNode* node = st.top();
st.pop();
if (node != NULL) result.push_back(node->val);
else continue; //重新执行循环,不执行后面语句
st.push(node->right);
st.push(node->left);
}
return result;
}
2.中序遍历
前序遍历先访问的是中间节点,处理的也是中间节点所以可以直接写出代码。但是中序遍历访问的顺序和处理的顺序不一致,在使用迭代法写中序遍历,需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。
中序遍历做法:先一直向左到底部,到最底之后开始出栈,每出栈一个就放入它的右孩子,实现代码如下:
//中序遍历
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode> st;
TreeNode* cur = root;
while(! st.empty() || cur != NULL) {
st.push(cur);
cur = cur->left;
}
else{
cur = st.top();
st.pop();
result.push_back(cur->val);
cur = cur->right;
}
}
3.后序遍历
前序遍历是中左右,后序遍历是左右中,调整一些前序遍历就可以变成中右左,再反转result就编程左右中,实现代码如下:
//后序遍历
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
st.push(root);
while(!st.empty()) {
TreeNode* node = st.top();
if (node!=NULL) st.pop();
else continue;
st.push(node->left);
st.push(node->right);
}
reverse(result.begin(), result.end());
return result;
}