【leetcode】94.二叉树的中序遍历

【leetcode】94.二叉树的中序遍历

/转载请说明出处与作者/

/作者:多巴胺dopamine/

1 问题描述

1.1 题目描述

给定一个二叉树的根节点root,返回它的中序遍历。

题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)

示例 1:

image

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

1.2 题目说明

本题是二叉树的中序遍历,相应的还有前序遍历和后序遍历。

这三种遍历均属于深度优先遍历,这三种遍历对应的代码,仅是部分代码顺序不一样,代码近似。

中序遍历:左,中,右(如果当前节点有左结点,那么就去遍历它的左结点,左结点全部遍历完后,再读取当前节点的值,之后再去遍历当前节点的右节点)

前序遍历:中,左,右

后序遍历:左,右,后

2 解决方法

2.1 解法一:递归

2.1.1 递归简述

一个函数执行的时候调用它自己。

2.1.2 递归使用条件

(1)问题能够分化为相似的子问题,解决子问题更加简单。

(2)有一个临界条件,不能够无限制的调用下去。必须有一个结束的条件,否则就是函数一直调用自己,永远没有停止。

2.1.3 代码(C语言附注释)

/**
 * 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 medium_order_traversal();
# define size_number 100

/*
* 初始化函数。初始化一些参数的值。
* 参数说明:
* root,树的根节点; returnSize,返回数组的大小,它是一个指针,获取它所指向地址的值,使用(*retrunSize)。
*/
int* inorderTraversal(struct TreeNode* root, int* returnSize){
  *returnSize=0;
  // 开辟返回数组的空间
  /// sizeof的使用参考:https://www.runoob.com/cplusplus/cpp-sizeof-operator.html
  /// malloc的使用参考:https://www.runoob.com/cprogramming/c-function-malloc.html
  int* return_array=(int *)malloc(sizeof(int)*size_number);
  // 调用中序遍历函数
  medium_order_traversal(root,returnSize,return_array);
  // 返回数组
  return return_array;
}
/*
* 中序遍历函数,递归
* 参数说明:
* root,树的根节点; returnSize,返回数组的大小; return_array,返回数组的指针。
*/
void medium_order_traversal(struct TreeNode* root,int* returnSize,int* return_array){
  // 临界条件:root==NULL,只有在root不为NULL的时候才会执行下面的函数。
  if(root){
    // 遍历当前节点的左节点,递归
    medium_order_traversal(root->left,returnSize,return_array);
    // 当前节点的左结点遍历结束后,读取当前节点的值
    return_array[*returnSize]=root->val;
    (*returnSize)++;
    // 遍历当前节点的右节点,递归。
    medium_order_traversal(root->right,returnSize,return_array);
  }
}

2.2 解法二:迭代(循环的意思)

2.2.1 迭代和递归的转换

递归实际上是系统为你维护了一个工作栈。(不了解栈的,可以先去了解一下)

而使用迭代,就是自己将这个工作栈模拟出来,并进行维护。

2.2.2 代码(C语附注释)

/**
 * 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 medium_order_traversal();
// 栈顶指针,栈底指针默认为0  
int top;

/*
* 初始化函数。初始化一些参数的值。
* 参数说明:
* root,树的根节点; returnSize,返回数组的大小,它是一个指针,获取它所指向地址的值,使用(*retrunSize)。
*/
int* inorderTraversal(struct TreeNode* root, int* returnSize){
  //栈的初始化
  top=0;
  //开辟栈空间,实际就是一个struct TreeNode指针的数组
  /// sizeof的使用参考:https://www.runoob.com/cplusplus/cpp-sizeof-operator.html
  /// malloc的使用参考:https://www.runoob.com/cprogramming/c-function-malloc.html
  struct TreeNode** stack=(struct TreeNode**)malloc(sizeof(struct TreeNode*)*100);
  
  *returnSize=0;
  //开辟返回数组空间
  int* return_array=(int*)malloc(sizeof(int)*100);  
  //调用中序遍历函数
  medium_order_traversal(root,returnSize,return_array,stack);
  //返回数组
  return return_array;
}
/*
* 中序遍历函数,迭代
* 参数说明:
* root,树的根节点; returnSize,返回数组的大小; return_array,返回数组的指针;stack,栈的指针
*/
void medium_order_traversal(struct TreeNode* root, int* returnSize,int* return_array,struct TreeNode** stack){
  //结束条件:栈为空且当前节点为NULL(即当前节点是叶子节点)(见解释一)
  while(top!=0||root!=NULL){
    
    //如果当前节点不为NULL,说明不是叶子结点,有值,执行下面代码。
    while(root!=NULL){
      //将当前节点入栈
      stack[top]=root;
      top++;
      //指针指向当前节点的左结点,然后再判断是不是叶子结点
      root=root->left;
    }
      //说明当前指针指向了叶子节点,没有值。将栈顶的节点出栈,读取其值
      top--;
      return_array[*returnSize]=(stack[top])->val;
      (*returnSize)++;
      //将当前指针换到刚刚读取节点的右节点
      root=(stack[top])->right;
  }
}

2.2.3 解释一

循环结束条件的确定(帮助理解,可以自己再画几个二叉树,来理解这个条件的确定)

例:

image

中序遍历结果应该为:D,B,E,A,C,F。

指针最后指向F的右节点,此时栈为空,该节点是叶子节点

其他任何时候,均不满足此条件。

posted @ 2022-08-07 11:43  多巴胺dopamine  阅读(38)  评论(0编辑  收藏  举报