当前位置: 首页 > news >正文

学习笔记—数据结构—二叉树(算法题)

目录

前言:

单值二叉树

问题描述

解题思路

代码

相同的树

问题描述

解题思路

代码

对称二叉树

问题描述

解题思路

代码

另一棵树的子树

问题描述

解题思路

代码

前序遍历

问题描述

解题思路

代码

中序遍历

问题描述

解题思路

代码

后序遍历

问题描述

解题思路

代码

⼆叉树的构建及遍历

问题描述

解题思路

代码


前言:

在之前我们学习了二叉树顺序实现和二叉树(链式),那么我们将进入算法题部分,Let's Go!

单值二叉树

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

问题描述

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

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

解题思路

如果root为空,则返回true

判断root->left不为空并且左子树root->left->val的值不等于根节点root->val的值,返回false

判断root->right不为空并且右子树root->right->val的值不等于根节点root->val的值,返回false

最后返回遍历左右子树

代码

typedef struct TreeNode TreeNode;
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);
}

相同的树

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

问题描述

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

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

解题思路

判断根节点p,q同时是否为空,为空返回ture

判断根节点p,q一个为空一个不为空,返回false

判断根节点p,q都不为空值不相等,返回false

最后根节点p,q都不为空且相等则进入遍历,p,q左右并且,p->left和q->left、p->right和q->right比较。

代码

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    //p,q同时为空
    if(p == NULL && q == NULL)
    {
        return true;
    }
    //p,q其中一个为空
    if(p == NULL || q == NULL)
    {
        return false;
    }
    //p,q都不为空但值不相等
    if(p->val != q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

对称二叉树

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

问题描述

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

解题思路

创建一个函数isSameTree函数

判断根节点p,q同时是否为空,为空返回ture

判断根节点p,q一个为空一个不为空,返回false

判断根节点p,q都不为空值不相等,返回false

根节点p,q都不为空且相等则进入遍历,p,q左右并且,p->left和q->right、p->right和q->left比较。

最后原函数返回isSameTree函数

代码

 bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    //p,q同时为空
    if(p == NULL && q == NULL)
    {
        return true;
    }
    //p,q其中一个为空
    if(p == NULL || q == NULL)
    {
        return false;
    }
    //p,q都不为空但值不相等
    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);
}

另一棵树的子树

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

问题描述

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

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

解题思路

创建相同的树isSameTree函数

判断如果root为空,为空返回false

判断如果root=subRoot则进入isSameTree函数看以root为根节点的树是否与subRoot完全相同,相同返回true

最后递归root->left和subRoot或root->right和subRoot

代码

 bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    //p,q同时为空
    if(p == NULL && q == NULL)
    {
        return true;
    }
    //p,q其中一个为空
    if(p == NULL || q == NULL)
    {
        return false;
    }
    //p,q都不为空但值不相等
    if(p->val != q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

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);
}

前序遍历

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

问题描述

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

解题思路

创建一个二叉树结点个数的函数TreeSize

创建一个递归二叉树保存节点函数_preorderTraversal,传根节点root、存储数组int*arr、形参int*pi

如果根节点root为空,返回

arr数组里的形参(*pi)++保存节点root的值

遍历左右节点

*returnSize储存结点函数TreeSize

创建int*returnArr储存动态申请空间arr大小

创建函数i

调用递归二叉树保存节点函数_preorderTraversal传root、returnArr、i

最后返回returnArr

代码

typedef struct TreeNode TreeNode;
int TreeSize(TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    return 1+TreeSize(root->left)+TreeSize(root->right);
}
void _preorderTraversal(TreeNode*root,int*arr,int*pi)
{
    if(root == NULL)
    {
        return ;
    }
    arr[(*pi)++]=root->val;
    _preorderTraversal(root->left,arr,pi);
    _preorderTraversal(root->right,arr,pi);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    //第一步:先求出二叉树节点个数
    *returnSize=TreeSize(root);
    //第二部:动态申请内容--arr数组
    int*returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    int i =0;
    _preorderTraversal(root,returnArr,&i);
    return returnArr;
}

中序遍历

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

问题描述

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

解题思路

创建一个二叉树结点个数的函数TreeSize

创建一个递归二叉树保存节点函数_inorderTraversal,传根节点root、存储数组int*arr、形参int*pi

如果根节点root为空,返回

遍历左节点

arr数组里的形参(*pi)++保存节点root的值

遍历右节点

*returnSize储存结点函数TreeSize

创建int*returnArr储存动态申请空间arr大小

创建函数i

调用递归二叉树保存节点函数_inorderTraversal传root、returnArr、i

最后返回returnArr

代码

typedef struct TreeNode TreeNode;
int TreeSize(TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    return 1+TreeSize(root->left)+TreeSize(root->right);
}
void _inorderTraversal(TreeNode*root,int*arr,int*pi)
{
    if(root == NULL)
    {
        return ;
    }
    _inorderTraversal(root->left,arr,pi);
    arr[(*pi)++]=root->val;
    _inorderTraversal(root->right,arr,pi);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    //第一步:先求出二叉树节点个数
    *returnSize=TreeSize(root);
    //第二部:动态申请内容--arr数组
    int*returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    int i =0;
    _inorderTraversal(root,returnArr,&i);
    return returnArr;
}

后序遍历

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

问题描述

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 

解题思路

创建一个二叉树结点个数的函数TreeSize

创建一个递归二叉树保存节点函数_postorderTraversal,传根节点root、存储数组int*arr、形参int*pi

如果根节点root为空,返回

遍历左右节点

arr数组里的形参(*pi)++保存节点root的值

*returnSize储存结点函数TreeSize

创建int*returnArr储存动态申请空间arr大小

创建函数i

调用递归二叉树保存节点函数_postorderTraversal传root、returnArr、i

最后返回returnArr

代码

typedef struct TreeNode TreeNode;
int TreeSize(TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    return 1+TreeSize(root->left)+TreeSize(root->right);
}
void _postorderTraversal(TreeNode*root,int*arr,int*pi)
{
    if(root == NULL)
    {
        return ;
    }
    _postorderTraversal(root->left,arr,pi);
    _postorderTraversal(root->right,arr,pi);
    arr[(*pi)++]=root->val;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    //第一步:先求出二叉树节点个数
    *returnSize=TreeSize(root);
    //第二部:动态申请内容--arr数组
    int*returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    int i =0;
    _postorderTraversal(root,returnArr,&i);
    return returnArr;
}

⼆叉树的构建及遍历

二叉树顺序实现

问题描述

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

输入描述:

输入包括1行字符串,长度不超过100。

输出描述:

可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行。

解题思路

代码

#include <stdio.h>
#include <stdlib.h>
/*
读取用户输入,保存在数组中,这个字符串的内容刚好是二叉树的前序遍历
 
我们根据这个前序遍历的结果来创建二叉树
 
再对二叉树进行中序遍历,输出中序遍历的结果
*/
/*
abc##de#g##f###
对于这个字符串,c是b的左子树,b是a的左子树
*/
 
 
/*
若遍历中没有给出NULL节点的情况,是不能根据某一个遍历来创建二叉树的
 
 
*/
typedef struct BinaryTreeNode//定义二叉树节点结构类型
{
    char data;
    struct BinaryTreeNode*left;
    struct BinaryTreeNode*right;
 
}BTNode;
 
BTNode*buyNode(char x)//创建节点
{
    BTNode*newnode=(BTNode*)malloc(sizeof(BTNode));
    newnode->data=x;
    newnode->left=newnode->right=NULL;
 
    return newnode;
}
 
BTNode*createTree(char*arr,int*pi)//创建二叉树,返回根节点,第一个参数是字符串,第二个参数是下标
{
    if(arr[*pi]=='#')
    {
        (*pi)++;//不要忘了往后面接着走
        return NULL;
    }
    BTNode*root=buyNode(arr[(*pi)++]);//将数组中的数据存储在二叉树中,将数组中的数据传到二叉树节点内
    root->left=createTree(arr,pi); //然后进行二叉树左节点的创建
    root->right=createTree(arr,pi); //二叉树右节点的创建
 
    return root;//返回根节点
}
void InOeder(BTNode*root)
{
    if(root==NULL)
    {
        return;
    }
    InOeder(root->left);//递归左子树
    printf("%c ",root->data);//打印根节点
    InOeder(root->right);//递归右子树
 
}
int main()
{
    //读取用户输入的字符串保存在字符数组中
    char arr[100];
    scanf("%s",arr);
 
    //根据字符串(前序遍历)创建二叉树
    int i=0;
    BTNode*root=createTree(arr,&i);
//这里的root是创建的二叉树的根节点
    //输出二叉树的中序遍历
    InOeder(root);
    return 0;
}

http://www.dtcms.com/a/108410.html

相关文章:

  • fyrox 2D和3D游戏的制作
  • 【云计算物理网络】数据中心网络架构设计
  • 蓝桥杯备考:完全二叉树的节点个数
  • mysql and redis简化版
  • 【Easylive】视频在线人数统计系统实现详解 WebSocket 及其在在线人数统计中的应用
  • 蓝桥杯DFS算法题(java)
  • RainbowDash 的旅行
  • HCIP的配置
  • 使用Python和OpenCV进行指纹识别与验证
  • 通过必应壁纸官方api实现网页背景图片随机展示
  • substring() 和 slice() 这两个方法的相同与不同
  • Python 脚本:自动化你的日常任务
  • 【element ui】翻页记忆功能、多选时执行删除操作,刷新表格问题
  • VS+Qt配置QtXlsx库实现execl文件导入导出(全教程)
  • 自动调整PPT文本框内容:防止溢出并智能截断文本
  • Shiro学习(三):shiro整合springboot
  • 城电科技 | 探秘零碳校园:创新应用,引领绿色未来
  • PHP在Debian环境上的并发处理能力如何
  • 深度学习处理文本(6)
  • STM32实现一个简单电灯
  • 2023年12月电子学会青少年软件编程四级考级真题—新“跳7”游戏
  • OpenCV
  • 系统与网络安全------Windows系统安全(5)
  • Maya软件中的约束基础:提高角色动画制作效率的关键技术
  • 【解决】Edge浏览器硬件加速问题:无法滚动与卡顿的应对方法
  • Lumerical ------ Edge coupler design
  • Test——BUG篇
  • 掌握 Git 的艺术:Rebase 和 Merge 的使用技巧
  • MySQL 中 LOCK TABLES(手动锁表) 语句的详细说明,包括语法、使用场景、示例代码及注意事项
  • c加加学习之day02