方法一:递归
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:
void helper(TreeNode* root, vector<int>& ve)
{
if (root == nullptr) return;
helper(root->left, std::ref(ve));
helper(root->right, std::ref(ve));
ve.emplace_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> ve;
helper(root, std::ref(ve));
return ve;
}
};
int main()
{
Solution A;
TreeNode* t = new TreeNode(2, nullptr, new TreeNode(3, new TreeNode(4, nullptr, nullptr), nullptr));
vector<int> ve = A.postorderTraversal(t);
return 0;
}
时间复杂度:O(n),其中 n 是二叉搜索树的节点数。每一个节点恰好被遍历一次
空间复杂度:O(n),为递归过程中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)
方法二:迭代
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> ve;
if (root == nullptr)return ve;
stack<TreeNode*> st;
TreeNode* prev = nullptr;
while (root != nullptr || !st.empty())
{
while (root != nullptr)
{
st.emplace(root);
root = root->left;
}
root = st.top(); st.pop();
if (root->right == nullptr || root->right == prev)
{
ve.emplace_back(root->val);
prev = root;
root = nullptr;
}
else
{
st.emplace(root);
root = root->right;
}
}
return ve;
}
};
int main()
{
Solution A;
TreeNode* t = new TreeNode(2, nullptr, new TreeNode(3, new TreeNode(4, nullptr, nullptr), nullptr));
vector<int> ve = A.postorderTraversal(t);
return 0;
}
时间复杂度:O(n),其中 n 是二叉搜索树的节点数。每一个节点恰好被遍历一次
空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为O(logn),最坏情况下树呈现链状,为 O(n)
方法三:Morris 遍历
后序遍历规则:
①新建临时节点,令该节点为 root;
②如果当前节点的左子节点为空,则遍历当前节点的右子节点;
③如果当前节点的左子节点不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点;
如果前驱节点的右子节点为空,将前驱节点的右子节点设置为当前节点,当前节点更新为当前节点的左子节点。
如果前驱节点的右子节点为当前节点,将它的右子节点重新设为空。倒序输出从当前节点的左子节点到该前驱节点这条路径上的所有节点。当前节点更新为当前节点的右子节点。
④重复步骤 2 和步骤 3,直到遍历结束。
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:
void addPath(vector<int>& vec, TreeNode* node)
{
int count = 0;
while (node != nullptr)
{
++count;
vec.emplace_back(node->val);
node = node->right;
}
reverse(vec.end() - count, vec.end());
}
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> ve;
if (root == nullptr) return ve;
TreeNode* tmp = root;
while (root != nullptr)
{
if (root->left != nullptr)
{
TreeNode* prodecessor = root->left;
while (prodecessor->right != nullptr && prodecessor->right != root)
{
prodecessor = prodecessor->right;
}
if (prodecessor->right == nullptr)
{
prodecessor->right = root;
root = root->left;
continue;
}
else
{
prodecessor->right = nullptr;
addPath(std::ref(ve), root->left);
}
}
root = root->right;
}
addPath(std::ref(ve), tmp);
return ve;
}
};
int main()
{
Solution A;
TreeNode* t = new TreeNode(2, nullptr, new TreeNode(3, new TreeNode(4, nullptr, nullptr), nullptr));
vector<int> ve = A.postorderTraversal(t);
return 0;
}
时间复杂度:O(n),其中 n 是二叉树的节点数。没有左子树的节点只被访问一次,有左子树的节点被访问两次。
空间复杂度:O(1),只操作已经存在的指针(树的空闲指针),因此只需要常数的额外空间