【数据结构】二叉树相关OJ题
创始人
2024-06-01 16:11:03
0

文章目录

  • 一、单值二叉树
  • 二、检查两颗树是否相同
  • 三、判断一棵树是否为另一颗树的子树
  • 四、对称二叉树
  • 五、二叉树的前序遍历
  • 六、二叉树中序遍历
  • 七、二叉树的后序遍历
  • 八、二叉树的构建及遍历

一、单值二叉树

单值二叉树

题目描述

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树,只有给定的树是单值二叉树时,才返回 true;否则返回 false

示例

在这里插入图片描述

思路分析

一棵树的所有节点都有相同的值,当且仅当对于树上的每一条边的两个端点,它们都有相同的值(这样根据传递性,所有节点都有相同的值)

因此,我们可以对树进行一次深度优先搜索,当搜索到节点root时,我们检查root的左孩子和右孩子是否相同,不相同则返回false,直到检查了所有的节点,所有我们就可以进行递归遍历,每次比较根节点和左右孩子的val值是否相等,不相等就返回false,然后递归比较左子树和右子树。

【注意】我们比较的条件应该是不相等,因为不相等就可以直接返回,而相等还要继续比较

代码实现

bool isUnivalTree(struct TreeNode* root)
{// 根节点为空返回trueif (root == NULL)return true;// 左子树存在但是不相等则返回falseif (root->left && root->val != root->left->val)return false;// 右子树存在但是不相等则返回falseif (root->right && root->val != root->right->val)return false;// 继续递归 左右子树return isUnivalTree(root->left) && isUnivalTree(root->right);
}

二、检查两颗树是否相同

题目链接

检查两颗树是否相同

题目描述

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

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

示例

在这里插入图片描述

思路分析

如果两个二叉树都为空,则两个二叉树相同。如果两个二叉树中有且只有一个为空,则两个二叉树一定不相同,如果两个二叉树都不为空,那么首先判断它们的根节点的值是否相同,若不相同则两个二叉树一定不同,若相同,再分别判断两个二叉树的左子树是否相同以及右子树是否相同。这是一个递归的过程,因此可以使用深度优先搜索,递归地判断两个二叉树是否相同。

代码实现

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{// 如果根节点都为NULL则返回tureif (p == NULL && q == NULL)return true;// 运行到这里,都不为空,则下面判断的情况为只有一个为空,另一个不为空,所以返回falseif (p == NULL || q == NULL)return false;// 都不为空但是值不相等返回falseif (p->val != q->val)return false;// 继续比较左右子树return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

在这里插入图片描述

三、判断一棵树是否为另一颗树的子树

题目链接

判断一棵树是否为另一颗树的子树

题目描述

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

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

示例

在这里插入图片描述

思路分析

由于root和subRoot中可能含有一个和多个值相同的节点,所以判断不相等的时候,又要返回原来的根节点,所以我们可以这道题利用上一题的代码,我们的思路为不断的比较root这棵树以每一个节点作为根节点,判断是否和subRoot相等,相等就返回true,所以节点都变量之后都没有相等的树就返回false.

代码实现

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{// 如果根节点都为NULL则返回tureif (p == NULL && q == NULL)return true;// 运行到这里,都不为空,则下面判断的情况为只有一个为空,另一个不为空,所以返回falseif (p == NULL || q == NULL)return false;// 都不为空但是值不相等返回falseif (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);}

在这里插入图片描述

四、对称二叉树

题目链接

对称二叉树

题目描述

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

示例

在这里插入图片描述

思路分析

这道题和判断两棵树是否相等的思路一致,只是有一些细节有所不同。对称二叉树是最左边和最右边的节点相同,所以我们就可以拿第一棵树的左子树和第二棵树的右子树进行比较,拿第一棵树的右子树和第二棵树的左子树进行比较,不相等就返回false,相等就继续比较,直到所有节点都相等,所以我们就可以对检查两颗是否相同的代码进行修改即可,即对其递归代码中的参数进行调整

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;}// 当两棵树中只有一棵树的节点为NULL时,节点数量不相等,直接返回falseif(p==NULL||q==NULL){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);
}

在这里插入图片描述

五、二叉树的前序遍历

题目链接

二叉树的前序遍历

题目描述

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

示例

在这里插入图片描述

思路分析

二叉树的前序遍历我们已经非常熟悉,这里我提出两点需要注意的地方:

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

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

代码实现

// 计算节点个数
int TreeSize(struct TreeNode* root)
{if (root == NULL)return 0;// 左子树的节点个数+右节点的个数+1return TreeSize(root->left) + TreeSize(root->right) + 1;
}
// 前序遍历并存入数组中
void preorder(struct TreeNode* root, int* a, int* pi)
{if (root == NULL)return;// 先遍历根,再访问左子树,左后访问右子树a[*pi] = root->val;(*pi)++;preorder(root->left, a, pi);preorder(root->right, a, pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{// 求二叉树的节点个数int size = TreeSize(root);// 开辟同等大小的空间int* a = (int*)malloc(sizeof(int) * size);int i = 0;//前序遍历preorder(root, a, &i);*returnSize = size;return a;
}

在这里插入图片描述

六、二叉树中序遍历

题目链接

二叉树中序遍历

题目描述

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

示例

在这里插入图片描述

二叉树的中序遍历和前序遍历一样,只是访问节点的顺序不同

代码实现

// 计算节点个数
int TreeSize(struct TreeNode* root)
{if (root == NULL)return 0;// 左子树的节点个数+右节点的个数+1return TreeSize(root->left) + TreeSize(root->right) + 1;
}
// 前序遍历并存入数组中
void inorder(struct TreeNode* root, int* a, int* pi)
{if (root == NULL)return;// 先遍历左子树,再访问根节点,左后访问右子树inorder(root->left, a, pi);a[*pi] = root->val;(*pi)++;inorder(root->right, a, pi);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize)
{// 求二叉树的节点个数int size = TreeSize(root);// 开辟同等大小的空间int* a = (int*)malloc(sizeof(int) * size);int i = 0;//中序遍历inorder(root, a, &i);*returnSize = size;return a;
}

在这里插入图片描述

七、二叉树的后序遍历

题目链接

二叉树的后序遍历

题目描述

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

示例

在这里插入图片描述

思路分析

二叉树的后序遍历和前序遍历,中序遍历一样,只是访问节点的顺序不同

代码实现

代码实现

// 计算节点个数
int TreeSize(struct TreeNode* root)
{if (root == NULL)return 0;// 左子树的节点个数+右节点的个数+1return TreeSize(root->left) + TreeSize(root->right) + 1;
}
// 后序遍历并存入数组中
void postorder(struct TreeNode* root, int* a, int* pi)
{if (root == NULL)return;// 先遍历左子树,再访问右子树,左后访问根节点postorder(root->left, a, pi);postorder(root->right, a, pi);a[*pi] = root->val;(*pi)++;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{// 求二叉树的节点个数int size = TreeSize(root);int* a = (int*)malloc(sizeof(int) * size);int i = 0;// 后续遍历postorder(root, a, &i);*returnSize = size;return a;
}

在这里插入图片描述

八、二叉树的构建及遍历

题目链接

二叉树的构建及遍历

题目描述

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

输入描述:

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

输出描述:

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

示例

在这里插入图片描述

思路分析

这道题目是前序建立二叉树和中序遍历,我们写成两个子函数即可,对于二叉树的创建,字符为‘#’说明节点为空,我们直接返回即可,然后依次递归创建节点即可

代码实现

#include 
#include // 符号和结构的定义
typedef char BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
} BTNode;// 构建二叉树
BTNode* BTreeCreate(char* 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 = BTreeCreate(a, pi);root->right = BTreeCreate(a, pi);return root;
}
// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){return;}// 先访问左子树,再访问根节点,最后访问右子树InOrder(root->left);printf("%c ", root->data);InOrder(root->right);
}int main()
{char str[100];scanf("%s", str);// 创建二叉树int i = 0;BTNode* root = BTreeCreate(str, &i);// 二叉树的中序遍历InOrder(root);return 0;
}

在这里插入图片描述

相关内容

热门资讯

乞讨者作文650字 乞讨者作文650字  说到乞丐,大家一定都不陌生,五山的街道旁随处可见。在路上开车的时候,车窗旁也会...
小朋友友谊作文400字 关于小朋友友谊作文400字汇总5篇  在平凡的学习、工作、生活中,大家总免不了要接触或使用作文吧,根...
我心目中的父母作文 我心目中的父母作文我心目中的父母有一种爱是无私的,有一种爱是伟大的,有一种爱是永恒的!这爱,刚开始起...
>有感 -作文 >有感 -作文  在平日的学习、工作和生活里,大家都不可避免地要接触到作文吧,借助作文人们可以反映客...
洛阳“龙门石窟”游记作文 洛阳“龙门石窟”游记作文  在日常学习、工作抑或是生活中,大家对作文都不陌生吧,借助作文人们可以实现...
掌声的作文 掌声的作文(10篇)  在平凡的学习、工作、生活中,大家都尝试过写作文吧,借助作文人们可以反映客观事...
写字之星作文 写字之星作文  我们班有一个“写字之星”—孔奕如!她的“雄伟事迹”已经很多了,准确来说是多的数不清!...
跳长绳优秀作文 跳长绳优秀作文(通用10篇)  在日常学习、工作或生活中,大家都写过作文,肯定对各类作文都很熟悉吧,...
我当按摩师作文 我当按摩师作文XX年03月13日 星期日晚上,我刚作完作业,就发现妈妈坐在床上一直用手揉着后背,我瞧...
春天的味道作文 春天的味道作文通用15篇  在现实生活或工作学习中,大家总少不了接触作文吧,作文要求篇章结构完整,一...
清响作文600字 清响作文600字  在我们平凡的日常里,大家总少不了接触作文吧,作文根据体裁的不同可以分为记叙文、说...
傅雷家书好词好句摘抄 傅雷家书好词好句摘抄  在现实社会中,大家肯定对各类好词好句都很熟悉吧,好词好句的积累对于写作文时可...
勇气作文 关于勇气作文(精选40篇)  在学习、工作、生活中,大家都写过作文,肯定对各类作文都很熟悉吧,根据写...
描写昆虫的优美段落 描写昆虫的优美段落  昆虫王国里有趣的昆虫多得数不清,凭我们现在对昆虫的认识还是肤浅的,我们还需要探...
人无完人作文500字 人无完人作文500字  “人无完人”这个成语用在我身上,那是最好不过的了。老师要求我们遵守的十三条良...
初三语文辅导作文600字 初三语文辅导作文600字  在日常生活或是工作学习中,大家最不陌生的就是作文了吧,写作文可以锻炼我们...
写景优美作文摘抄好句好段 写景优美作文摘抄好句好段大全  大家都写过作文,肯定对各类作文都很熟悉吧,尤其是充满意境的写景作文,...
成长类的作文 成长类的作文(精选5篇)  在日常学习、工作抑或是生活中,大家对作文都再熟悉不过了吧,借助作文可以提...
柳作文 柳作文  在平日的学习、工作和生活里,大家都有写作文的经历,对作文很是熟悉吧,借助作文人们可以实现文...
洗菜作文400字 洗菜作文400字四篇  在日常学习、工作或生活中,大家都有写作文的经历,对作文很是熟悉吧,写作文是培...