代码随想录训练营-12day-二叉树1

一、二叉树理论基础

1 理解满二叉树,完全二叉树,平衡二叉树和二叉搜索树的概念;

2 二叉树存储方式:其一是数组线性存储;其二是链表链式存储;

3 二叉树遍历方式:1)前序遍历;2)中序遍历;3)后序遍历;

4 二叉树定义:

struct TreeNode
{
   int* val;
   struct TreeNode* left;
   struct TreeNode* right;
}

5 二叉树的遍历方法:1) 递归方法;2)迭代方法;

    1)递归

     a.递归函数的参数和返回值;

     b.确定终止条件

     c.确定单层递归逻辑

leetcode题目:

144. 前序遍历:
/**
 * 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 traversal(struct TreeNode* cur, int* result, int* index)
 {   
    /**前序遍历 中-左-右**/
    if(cur == NULL) return;
    result[(*index)++] = cur->val;
    traversal(cur->left, result, index);
    traversal(cur->right, result, index);
 }
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
    struct TreeNode* cur = root;
    *returnSize = 0;
    traversal(cur, result, returnSize);
    return result;
}
94. 中序遍历

/**
 * 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 traversal(struct TreeNode* cur, int* result, int* index)
 {   
    /**中序遍历 左-中-右**/
    if(cur == NULL) return;
    traversal(cur->left, result, index);
    result[(*index)++] = cur->val;
    traversal(cur->right, result, index);
 }
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
    struct TreeNode* cur = root;
    *returnSize = 0;
    traversal(cur, result, returnSize);
    return result;
}
145.后序遍历
/**
 * 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 traversal(struct TreeNode* cur, int* result, int* index)
 {   
    /**后序遍历 左-右-中**/
    if(cur == NULL) return;
    traversal(cur->left, result, index);
    traversal(cur->right, result, index);
    result[(*index)++] = cur->val;
 }

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
    struct TreeNode* cur = root;
    *returnSize = 0;
    traversal(cur, result, returnSize);
    return result;
}

    2)迭代

        前序和后序遍历可以统一成为一个code风格,前序调整顺序再翻转数组就是后序。

        注意点:a. 用数组来保存节点(指针);b. cur指针的位置变化

/**迭代法**/
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    *returnSize = 0;
    if(root == NULL)
       return NULL;
    int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
    struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 110);//用来做栈
    int stk_idx = 0;
    struct TreeNode* cur = root;
    //traversal(cur, result, returnSize);
    /**前序遍历 先把中间节点数值压入栈内**/
    stk[stk_idx++] = root;
    while(stk_idx > 0)
    {
        /**节点值放入result**/
       result[(*returnSize)++] = (stk[--stk_idx])->val;//stk_indx填了数字 位置加了1
       cur = stk[stk_idx];
       /**压入右节点, 后压入左节点**/      
       if(cur->right)
       {
         stk[stk_idx++] = cur->right; 
       }
       if(cur->left)
       {
         stk[stk_idx++] = cur->left; 
       }
    }
    return result;
}

 //另外提供一种写法,和栈契合度高些
 /** 栈的思想
 前序遍历:中左右
 头节点先入栈;
 当栈不为空,一直执行下面操作:
 1-从栈中pop元素作为当前节点,写入数组中;
 2-因为栈是先入后出,所以先把右边的节点入栈,再入左边的,这样出栈时候就先左后右
 3-直到栈元素为空
 **/
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    /**用数组模拟栈**/
    int stk_base = -1;//栈底位置
    *returnSize = 0;
    struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 101);
    NodeList[++stk_base] = root;
    int* result = (int*)malloc(sizeof(int) * 101);
    if(root == NULL)
    {
        return NULL;
    }
    /**栈不为空时候**/
    while(stk_base > -1)
    {
        //pop出栈
        struct TreeNode* curNode =  NodeList[stk_base];
        result[(*returnSize)++] = curNode->val;
        stk_base--;//相当于出栈

        //把右节点 左节点入栈
        if(curNode->right)
            NodeList[++stk_base] = curNode->right;
        if(curNode->left)
            NodeList[++stk_base] = curNode->left;
    }
    return result;
}

/**迭代法**/
void reserve(int* arr, int size)
{
    int left = 0;
    int right = size -1;
    while(left < right)
    {
        int tmp = arr[right];
        arr[right] = arr[left];
        arr[left] = tmp;

        left++;
        right--;
    }
}
int* postorderTraversal(struct TreeNode* root, int* returnSize)  {
    *returnSize = 0;
    if(root == NULL)
       return NULL;
    int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
    struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 110);//用来做栈
    int stk_idx = 0;
    struct TreeNode* cur = root;
    //traversal(cur, result, returnSize);
    /**前序遍历 先把中间节点数值压入栈内**/
    stk[stk_idx++] = root;
    while(stk_idx > 0)
    {
        /**节点值放入result**/
       result[(*returnSize)++] = (stk[--stk_idx])->val;//stk_indx填了数字 位置加了1
       cur = stk[stk_idx];
       /**压入左节点, 后压入右节点**/      
       if(cur->left)
       {
         stk[stk_idx++] = cur->left; 
       }       
       if(cur->right)
       {
         stk[stk_idx++] = cur->right; 
       }
    }
    reserve(result, *returnSize);
    return result;
}

        中序遍历:

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    *returnSize = 0;
    if(root == NULL)
       return NULL;
    int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
    struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 110);//用来做栈
    int stk_idx = 0;
    struct TreeNode* cur = root;
    //traversal(cur, result, returnSize);
    while(stk_idx > 0 || cur)
    {
        /**如果cur不为空,一直往左子树遍历,加入栈中**/
        if(cur)
        {
           stk[stk_idx++] = cur;
           cur = cur->left;
        }
        else
        {
            //保存中间数值
           result[(*returnSize)++] = (stk[--stk_idx])->val;
           cur = stk[stk_idx];//当前是栈弹出的node
           //save right node
           cur = cur->right;
        }
    }
    return result;
}

此外,代码随想录提供思路,把迭代法统一风格,就是在入栈时候,加入节点同时,也加入一个空节点进行标记。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值