前序遍历
前序遍历/前序遍历oj
1.递归写法
class Solution {
public:
vector<int> ret;
vector<int> preorderTraversal(TreeNode* root) {
if(root != NULL){
ret.push_back(root -> val);
preorderTraversal(root -> left);
preorderTraversal(root -> right);
}
return ret;
}
};
//插入根节点,只需递归访问左右子树即可
非递归写法,迭代完成
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> ret;
TreeNode *cur = root;
while(cur || !st.empty())
{
while(cur)
{
ret.push_back(cur->val);
st.push(cur);
cur = cur->left;
}
TreeNode *top = st.top();
st.pop();
cur = top->right;
}
return ret;
}
};
中序遍历
中序遍历OJ
递归写法
class Solution {
public:
vector<int> ret;
vector<int> inorderTraversal(TreeNode* root) {
if (root != NULL)
{
inorderTraversal(root->left);
ret.push_back(root->val);
inorderTraversal(root->right);
}
return ret;
}
};
非递归写法
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> ret;
TreeNode *cur = root;
while(cur || !st.empty())
{
while(cur)
{
st.push(cur);
cur = cur->left;
}
TreeNode *top = st.top();
ret.push_back(top->val);
st.pop();
cur = top->right;
}
return ret;
}
};
和前序遍历类似,不同点在于,前序遍历顺序为根,左,右;中序为左,根,右,所以插入数据的时候必须先插入最后一个左子树的节点,也就是出栈第一个元素。
后序遍历
后序遍历OJ
递归写法
class Solution {
public:
vector<int> ret;
vector<int> postorderTraversal(TreeNode* root)
{
if(root != NULL)
{
postorderTraversal(root->left);
postorderTraversal(root->right);
ret.push_back(root -> val);
}
return ret;
}
};
非递归(迭代)
基本思路和先序,中序一样,只是需要加一个判断,后序遍历的顺序为左,右,根。即访问完左子树之后,需要判断右子树是否为空,如果不为空,需要访问完之后返回根节点访问,难点在于处理这个根节点,因为如果只是简单的判断右子树是否为空,则会陷入死循环,所以使用双指针,如右子树不为空,记录节点,加上判断即可。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root)
{
stack<TreeNode*> st;
vector<int> ret;
TreeNode* cur = root;
TreeNode* last;
while(cur || !st.empty())
{
while(cur)
{
st.push(cur);
cur = cur->left;
}
TreeNode* top = st.top();
if(top->right == NULL || top->right == last)
{
ret.push_back(top->val);
last = top;
st.pop();
}
else
cur = top->right;
}
return ret;
}
};