二叉树遍历

中序遍历

https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

递归

这里直接判断左右节点是否是NULL,意味着不需要将节点下移到叶子节点,在下一次递归的时候再判断,个人认为这样会好一点,虽然代码逻辑会复杂一点。

递归的对象是子树,那么传递的参数主要就是根节点;

递归的思路很简单:
如果有左子树,就先递归左子树(因为这一步不需要保存左叶子,因此暂时不考虑);
递归完左子树后,或者没有左子树了,就保存根节点;
如果有右子树就递归右子树(因为这一步不需要保存右叶子,因此暂时不考虑);

考虑一下叶子是否被保存了,是的,因为叶子可以看作NULL的根,所以在递归到最底层会被保存。

最后考虑一下需不需要返回值,每次递归只需要处理子树,子树不需要反馈父树什么内容,因此不需要返回值。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void mid_fun(struct TreeNode* node,int* out, int* returnSize){
    printf("%d,",node->val);
    if(node->left != NULL){
        mid_fun(node->left,out,returnSize);
    }
    
    out[*returnSize] = node->val;
    (*returnSize)++;
    
    if(node->right != NULL){
        mid_fun(node->right,out,returnSize);
    }
}
#define N 200
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = 0;
    if(root==NULL){
        return NULL;
    }
    int res[N] = {0};

    mid_fun(root,res,returnSize);
    
    // printf("%d===",*returnSize);
    // for(int i=0;i<*returnSize;i++){
    //     printf("%d,",res[i]);
    // }
    
    int *res0 = malloc((*returnSize)*sizeof(int));
    memcpy(res0,res,(*returnSize)*sizeof(int));
    return res0;
}

何时入栈?对每一个节点先沿左子树遍历,对每一个路过的节点入栈。
入栈顺序?先入栈所有的左节点,出栈保存后,即入栈右节点。
何时出栈?出栈时保存。当遍历到每个子树最左端的叶子节点后,开始出栈。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
#define N 200
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = 0;
    if(root==NULL){
        return NULL;
    }
    struct TreeNode* stack[N] = {0};
    int stacktop = -1;
    int res[N] = {0};

    struct TreeNode *p = root;
    while(stacktop!=-1 || p != NULL){//栈不为空
        while(p!=NULL){
            stack[++stacktop] = p;
            p = p->left;
        }
        p = stack[stacktop--];
        res[*returnSize] = p->val;
        (*returnSize)++;
        p = p->right;
    }

    int *res0 = malloc((*returnSize)*sizeof(int));
    memcpy(res0,res,(*returnSize)*sizeof(int));
    return res0;
}

前序遍历

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

递归

因为要先保存根节点,因此换一下顺序就行了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


void left_fun(struct TreeNode* node,int* out, int* returnSize){
    // printf("%d,",node->val);
    out[*returnSize] = node->val;
    (*returnSize)++;

    if(node->left != NULL){
        left_fun(node->left,out,returnSize);
    }
    
    if(node->right != NULL){
        left_fun(node->right,out,returnSize);
    }
}
#define N 200
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = 0;
    if(root==NULL){
        return NULL;
    }
    int res[N] = {0};

    left_fun(root,res,returnSize);
    
    // printf("%d===",*returnSize);
    // for(int i=0;i<*returnSize;i++){
    //     printf("%d,",res[i]);
    // }
    
    int *res0 = malloc((*returnSize)*sizeof(int));
    memcpy(res0,res,(*returnSize)*sizeof(int));
    return res0;
}

我们要把根节点保存起来,不然访问到叶子节点后就丢失整个树了。观察递归的代码,我们发现保存叶子节点和保存根节点的动作是一致的,因此我们规定,入栈不保存,出栈时保存,下一个解决的问题就是何时入栈,何时出栈,入栈顺序的问题了。
何时入栈:因为树结构保存在栈中,因此得到一个节点后想要迭代到叶子节点,必须先把叶子节点都保存起来,因此出栈后就把这个节点的叶子节点按照(右-左)顺序入栈;
入栈顺序:按照右-左顺序入栈,出栈时就是左-右,符合要求。
何时出栈:刚开始root入栈,之后就开始迭代,没出栈一个节点就处理当前节点,直到栈空。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

#define N 200
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = 0;
    if(root==NULL){
        return NULL;
    }
    struct TreeNode* stack[N] = {0};
    int stacktop = -1;
    int res[N] = {0};

    struct TreeNode *p;
    stack[++stacktop] = root;//根节点入栈
    while(stacktop!=-1){//栈不为空
        p = stack[stacktop--];
        res[*returnSize] = p->val;
        (*returnSize)++;
        if(p->right != NULL) stack[++stacktop] = p->right;
        if(p->left != NULL) stack[++stacktop] = p->left;
    }

    // printf("%d===",*returnSize);
    // for(int i=0;i<*returnSize;i++){
    //     printf("%d,",res[i]);
    // }

    int *res0 = malloc((*returnSize)*sizeof(int));
    memcpy(res0,res,(*returnSize)*sizeof(int));
    return res0;
}

后序遍历

https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


void right_fun(struct TreeNode* node,int* out, int* returnSize){
    // printf("%d,",node->val);
    if(node->left != NULL){
        right_fun(node->left,out,returnSize);
    }
    
    if(node->right != NULL){
        right_fun(node->right,out,returnSize);
    }

    out[*returnSize] = node->val;
    (*returnSize)++;
}
#define N 200
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* postorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = 0;
    if(root==NULL){
        return NULL;
    }
    int res[N] = {0};

    right_fun(root,res,returnSize);
    
    // printf("%d===",*returnSize);
    // for(int i=0;i<*returnSize;i++){
    //     printf("%d,",res[i]);
    // }
    
    int *res0 = malloc((*returnSize)*sizeof(int));
    memcpy(res0,res,(*returnSize)*sizeof(int));
    return res0;
}

这个可以考虑和中序遍历一样的方法,先遍历到最左边的叶子,但是这意味着在遍历过程中需要把大半个树入栈。在网上看到下面这种方法不错:
和前序遍历一样,只不过交换一下左右子树入栈顺序,最后得到的结果是”右左中“,那么只需要对结果反转便可以了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
#define N 200
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* postorderTraversal(struct TreeNode* root, int* returnSize){    
    *returnSize = 0;
    if(root==NULL){
        return NULL;
    }
    struct TreeNode* stack[N] = {0};
    int stacktop = -1;
    int res[N] = {0};

    struct TreeNode *p;
    //对每一层按序存入(右左),出栈保存
    stack[++stacktop] = root;//根节点入栈
    while(stacktop!=-1){//栈不为空
        p = stack[stacktop--];
        res[*returnSize] = p->val;
        (*returnSize)++;
        if(p->left != NULL) stack[++stacktop] = p->left;
        if(p->right != NULL) stack[++stacktop] = p->right;
    }

    int *res0 = malloc((*returnSize)*sizeof(int));
    for(int i=0;i<*returnSize;i++){
        res0[i] = res[(*returnSize)-i-1];
    }
    return res0;
}

层次遍历

这个用队列可以轻松实现,就不说了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朽木白露

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值