目录
一、前言
本篇文章主要讲解二叉树的后序遍历,对前序遍历、中序遍历不熟悉的同学可以观看本专栏。
二、后序遍历
简单来说,前序遍历的遍历思想就是: 左子树 ---> 右子树--->根结点。
图一 后序遍历
如何在不编程的情况下快速计算二叉树的中序遍历呢?接下来我教给大家一个简单快捷的方法。
图二 小孔穿线法
这种快速计算方法我给起名为小孔穿线法,后序遍历的小孔穿线法就是在该二叉树的每个节点的右侧画一个小孔,然后依次连接起来,如图二所示,所以该二叉树的后序遍历结果为[4、5、2、6、7、3、1]。
当然该方法是为了让大家不通过编程来进行快速计算的,接下来我将从递归和迭代两种编程方法为大家讲解。(Morris算法本篇文章暂且先不讲,请关注后续)
三、递归
二叉树遍历,递归思想其实是最简单的方法。后序遍历我们递归的思想就是左子树 ---> 右子树--->根结点。我直接给伪代码了,不懂的同学可以私信或评论区问我。
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void postorder(struct TreeNode* root, int* res, int* resSize)
{
if( !root )
{
return ;
}
postorder(root->left, res, resSize);
postorder(root->right, res, resSize);
res[(*resSize)++] = root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
int* res = malloc(sizeof(int)*100);
*returnSize = 0;
postorder(root, res, returnSize);
return res;
}
时间复杂度:o(n)
空间复杂度:o(1)
四、迭代
递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码。
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
int* res = malloc(sizeof(int)*100);
*returnSize = 0;
struct TreeNode** stack = malloc(sizeof(struct TreeNode*)*100);
int top = 0;
struct TreeNode* prev = NULL;
while( root != NULL || top > 0 )
{
while( root != NULL )
{
stack[top++] = root;
root = root->left;
}
root = stack[--top];
if(root->right == NULL || root->right == prev )
{
res[(*returnSize)++] = root->val;
prev = root;
root = NULL;
}
else
{
stack[top++] = root;
root = root->right;
}
}
return res;
}
时间复杂度:o(n)
空间复杂度:o(1)