【数据结构】二叉树相关OJ题

简介: 【数据结构】二叉树相关OJ题

一、单值二叉树

题目链接

965. 单值二叉树 - 力扣(LeetCode)

题目描述

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false

思路分析

递归解决:先比较根节点和两个子节点的val,如果不相等就返回false,相等就返回true,然后递归比较左子树和右子树。

代码实现

bool isUnivalTree(struct TreeNode* root){
    if(root == NULL)
        return true;
    if(root->left && root->left->val != root->val)
        return false;
    if(root->right && root->right->val != root->val)
        return false;
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

2020062310470442.png

二、相同的树

题目链接

100. 相同的树 - 力扣(LeetCode)

题目描述

给你两棵二叉树的根节点 pq ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

2020062310470442.png

思路分析

递归解决:比较两棵树根节点的val是否相同,在递归比较左右子树节点的val是否相同。

代码实现

//思路:检查节点的值或者节点的数量是否相同,如果不同直接返回false,然后递归检查左右子树是否相同
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
    if(p == NULL && q == NULL)
        return true;
    if(p == NULL || q == NULL)  //当两棵树中只有一棵树的节点为空时,节点数量不相同时,直接返回false
        return false;
    //检查节点和值是否相同
    if(p->val != q->val)  
        return false;
    //检查左右子树是否相同
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

2020062310470442.png

三、对称二叉树

题目链接

101. 对称二叉树 - 力扣(LeetCode)

题目描述

给你一个二叉树的根节点 root , 检查它是否轴对称。

2020062310470442.png

思路分析

这道题是上面那道题的一个简单变形,二者在实现思路上大致一样,只是细节上有所不同而已。

由于对称结构是最左边和最右边的节点相同,所以我们需要对 检查两棵子树是否对称 的代码中递归的参数进行调整:

return isSameTree(p->left, q->right) && isSameTree(p->right, q->left);

代码实现

//检查两棵子树是否对称
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
    if(p == NULL && q == NULL)
        return true;
    if(p == NULL || q == NULL)  //当两棵树中只有一棵树的节点为空时,节点数量不相同时,直接返回false
        return false;
    //检查节点和值是否相同
    if(p->val != q->val)  
        return false;
    //检查左右子树是否对称
    return isSameTree(p->left, q->right) && isSameTree(p->right, q->left);
}
//思路:将二叉树分为左子树和右子树,检查两棵子树是否对称
bool isSymmetric(struct TreeNode* root){
    return isSameTree(root->left, root->right);
}

2020062310470442.png

四、二叉树的前序遍历

题目链接

144. 二叉树的前序遍历 - 力扣(LeetCode)

题目描述

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

思路分析

思路分析


二叉树的前序遍历在前面我们已经学过,只是这里有两点需要注意的地方:


1、由于二叉树的节点数数未知的,为了不浪费空间,我们可以先求出二叉树的节点数,然后再开辟对应大小的空间;


2、由于数据是存储在一个数组中,所以我们需要一个变量 i 来控制数组的下标;同时,由于在递归调用过程中对形参的改变不会影响实参,所以这里我们需要传递 i 的地址,通过指针来控制 i 的增长。


代码实现

// 二叉树节点个数
int BinaryTreeSize(struct TreeNode* root)
{
  if (root == NULL)
    return 0;
  //左子树节点个数+右子树节点个数+根节点
  return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
// 二叉树前序遍历
void BinaryTreePrevOrder(struct TreeNode* root, int* ret, int* pi)
{
  if (root == NULL)
  {
    return;
  }
  //先访问根,再访问左子树,最后访问右子树
  ret[*pi] = root->val;
    (*pi)++;
  BinaryTreePrevOrder(root->left, ret, pi);
  BinaryTreePrevOrder(root->right, ret, pi);
}
 //思路:求出二叉树的节点个数,然后malloc等长的数组来存储节点值,最后通过前序遍历将节点值放入数组中
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    //求二叉树节点个数
    int n = BinaryTreeSize(root);
    int* ret = (int*)malloc(sizeof(struct TreeNode)*n);
    //前序遍历
    int i = 0;
    BinaryTreePrevOrder(root, ret, &i);
    *returnSize = i;
    return ret;
}

2020062310470442.png

五、二叉树的中序遍历

题目链接

94. 二叉树的中序遍历 - 力扣(LeetCode)

题目描述

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

思路分析

前序遍历和中序遍历基本上是一样的,只是访问顺序改变而已。

代码实现

// 二叉树节点个数
int BinaryTreeSize(struct TreeNode* root)
{
  if (root == NULL)
    return 0;
  //左子树节点个数+右子树节点个数+根节点
  return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
// 二叉树中序遍历
void BinaryTreeInOrder(struct TreeNode* root, int* ret, int* pi)
{
  if (root == NULL)
  {
    return;
  }
  //先访问左子树,再访问根,最后访问右子树
  BinaryTreeInOrder(root->left, ret, pi);
  ret[*pi] = root->val;
    (*pi)++;
  BinaryTreeInOrder(root->right, ret, pi);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    //求二叉树节点个数
    int n = BinaryTreeSize(root);
    int* ret = (int*)malloc(sizeof(struct TreeNode)*n);
    //前序遍历
    int i = 0;
    BinaryTreeInOrder(root, ret, &i);
    *returnSize = i;
    return ret;
}

2020062310470442.png

六、二叉树的后序遍历

题目链接

145. 二叉树的后序遍历 - 力扣(LeetCode)

题目描述

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

思路分析

后序遍历和前序、中序遍历基本上是一样的,只是访问顺序改变而已。

代码实现

// 二叉树节点个数
int BinaryTreeSize(struct TreeNode* root)
{
  if (root == NULL)
    return 0;
  //左子树节点个数+右子树节点个数+根节点
  return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
// 二叉树前序遍历
void BinaryTreePostOrder(struct TreeNode* root, int* ret, int* pi)
{
  if (root == NULL)
  {
    return;
  }
  //先访问根,再访问左子树,最后访问右子树
  BinaryTreePostOrder(root->left, ret, pi);
  BinaryTreePostOrder(root->right, ret, pi);
    ret[*pi] = root->val;
    (*pi)++;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
    //求二叉树节点个数
    int n = BinaryTreeSize(root);
    int* ret = (int*)malloc(sizeof(struct TreeNode)*n);
    //前序遍历
    int i = 0;
    BinaryTreePostOrder(root, ret, &i);
    *returnSize = i;
    return ret;
}

2020062310470442.png

七、另一棵树的子树

题目链接

572. 另一棵树的子树 - 力扣(LeetCode)

题目描述

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

2020062310470442.png

思路分析

由于root 和 subRoot 中可能含有一个或多个值相同的节点,所以我们只能遍历root,取出其中的每一个节点与subRoot进行比较,看是否相同。

代码实现

//思路:检查节点的值或者节点的数量是否相同,如果不同直接返回false,然后递归检查左右子树是否相同
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
    if(p == NULL && q == NULL)
        return true;
    if(p == NULL || q == NULL)  //当两棵树中只有一棵树的节点为空时,节点数量不相同时,直接返回false
        return false;
    //检查节点和值是否相同
    if(p->val != q->val)  
        return false;
    //检查左右子树是否相同
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
//思路:遍历root,取root的每一棵子树与sunroot比较,如果相同,就返回true
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    if(root == NULL)
        return false;
    if(isSameTree(root, subRoot))
        return true;
    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

2020062310470442.png

九、二叉树构建及遍历

题目链接

二叉树遍历_牛客题霸_牛客网 (nowcoder.com)

题目描述

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

示例1

输入:abc##de#g##f###
输出:c b e g d f a 

思路分析

这道题就是把二叉树的构建和二叉树的遍历结合到了一起而已,我们分别完全这两个功能即可。

代码实现

#include <stdio.h>
#include <stdlib.h>
//符号和结构的定义
typedef char BTDataType;
typedef struct BinaryTreeNode
{
  BTDataType data;
  struct BinaryTreeNode* left;
  struct BinaryTreeNode* right;
}BTNode;
//构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
  if (a[*pi] == '#')
  {
    (*pi)++;
    return NULL;
  }
  //创建根节点
  BTNode* root = (BTNode*)malloc(sizeof(BTNode));
  if (root == NULL)
  {
    perror("malloc fail");
    exit(-1);
  }
  root->data = a[*pi];
  (*pi)++;
  //创建左右子树
  root->left = BinaryTreeCreate(a, pi);
  root->right = BinaryTreeCreate(a, pi);
  return root;
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
  if (root == NULL)
  {
    return;
  }
  //先访问左子树,再访问根,最后访问右子树
  BinaryTreeInOrder(root->left);
  printf("%c ", root->data);
  BinaryTreeInOrder(root->right);
}
int main()
{
    char arr[100];
    scanf("%s", arr);
    //构建二叉树
    int i = 0;
    BTNode* root = BinaryTreeCreate(arr, &i);
    //二叉树的中序遍历
    BinaryTreeInOrder(root);
    return 0;
}

2020062310470442.png


相关文章
|
14天前
|
存储 机器学习/深度学习
【数据结构】二叉树全攻略,从实现到应用详解
本文介绍了树形结构及其重要类型——二叉树。树由若干节点组成,具有层次关系。二叉树每个节点最多有两个子树,分为左子树和右子树。文中详细描述了二叉树的不同类型,如完全二叉树、满二叉树、平衡二叉树及搜索二叉树,并阐述了二叉树的基本性质与存储方式。此外,还介绍了二叉树的实现方法,包括节点定义、遍历方式(前序、中序、后序、层序遍历),并提供了多个示例代码,帮助理解二叉树的基本操作。
38 13
【数据结构】二叉树全攻略,从实现到应用详解
|
11天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
11天前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
11天前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
1月前
|
存储
【初阶数据结构篇】二叉树基础概念
有⼀个特殊的结点,称为根结点,根结点没有前驱结点。
|
1月前
|
算法
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
【数据结构】树、二叉树与堆(长期维护)(2)
|
1月前
|
算法
【初阶数据结构篇】二叉树算法题
二叉树是否对称,即左右子树是否对称.
|
1月前
|
存储
【初阶数据结构篇】实现链式结构二叉树(二叉链)下篇
要改变root指针的指向,将本来指向根节点的root指针改为空,所以传二级指针(一级指针也可以,只不过在调用完记得把root置为空)。
|
1月前
|
存储 测试技术
【初阶数据结构篇】实现链式结构二叉树(二叉链)上篇
先构建根结点,再对左右子树构建,每次需要时申请一个结点空间即可,否则返回空指针。
|
1月前
|
存储 算法 测试技术
【初阶数据结构篇】实现顺序结构二叉树(堆的实现方法)
注意传过去的参数是插入的位置,即插入前的size,在调整完后再将size++