目录
8.二叉树遍历_牛客题霸_牛客网 (nowcoder.com)
(温馨提示:这里的标题本身就是题的链接)
1. 965. 单值二叉树
题目:
bool isUnivalTree(struct TreeNode* root){
if(root==NULL)//为空结点说明这一个支线已经相同,就返回true
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);//继续向下判断
}
单值二叉树就是所有节点值相同的二叉树,若要判断所有结点值相同,首先要思路就是判断根结点和左右孩子的值是否相同,如果相同,不能返回true,因为下面的结点还没判断,还要继续判断左孩子是否和他的左右结点值相同,右孩子是否和他自己的左右结点值相同,放 是否相同 就没办法放返回值了,所以这里的if语句不能放是否值相同,应该放 值是否不相同,不相同就返回false。
过程是:先判断根节点是不是空结点,是空结点也算单值,返回true;如果不是空结点,先判断根节点和左孩子值是否相同,不相同返回false,相同继续判断根和右孩子值是否相同:不相同返回false,相同的话继续重复判断左孩子是否和他的左右结点值相同,右孩子是否和他自己的左右结点值相同。一直到传入叶子结点,说明上面的结点都相同了,叶子结点不为空,但是他的左右孩子都是空,就不能访问左右孩子的值,所以要加上判断左右孩子是否为空的条件,为空就是叶子,左右是空就不用比较了,返回true。
2. 100. 相同的树
(温馨提示:这里的标题本身就是链接)
题目:
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p==NULL&&q==NULL) //①节点全为空则相同返回true
return true;
if(p==NULL||q==NULL) //②节点一空一非空一定不同返回false
return false;
if(p->val!=q->val) //③两节点都是非空,判断不相同返回false
return false;
return isSameTree(p->left, q->left)&&isSameTree(p->right, q->right); //继续向下比较左右节点
}
比两颗二叉树是否相同有三种情况:①节点全为空则相同返回true ②节点一空一非空一定不同返回false ③两个节点都是非空,不相同返回false,如果if条件设成相同,成立了也不能返回,还得继续向下比,所以不能设为相同而需要设成不相同返回false才能继续比较,如果相同不返回false,继续比较下面的左右节点即可。
3. 101. 对称二叉树
(温馨提示:这里的标题本身就是链接)
题目:
bool _isSymmetric(struct TreeNode* p,struct TreeNode* q)
{
if(p==NULL&&q==NULL)
return true;
if(p==NULL||q==NULL)
return false;
if(p->val!=q->val)
return false;
return _isSymmetric(p->left, q->right)&&_isSymmetric(p->right, q->left);
}
bool isSymmetric(struct TreeNode* root){
if(root==NULL)//只有一个空节点时是对称返回true。 当比较到叶子下面的空节点时说明对称,返回true
return true;
return _isSymmetric(root->left,root->right); //利用对称函数判断是否对称,根节点不用比较,所以从左右节点开始
}
①只有一个空节点时是对称返回true。 当比较到叶子下面的空节点时说明对称,返回true
②利用对称函数判断是否对称,根节点不用比较,所以从左右节点开始
③_isSymmetric 判断对称函数相当于是把判断二叉树相同函数进行修改;把根节点的左右子树看成两个树传入此函数,判断两个树是否相同时我们拿树1和树2的相同位置节点相比较:
【 return _isSymmetric(p->left, q->left)&&_isSymmetric(p->right, q->right); 】
这里是拿对称的位置进行比较,只要把传入的两个节点改成一左一右就成为比较两树是否对称的函数了:
【 return _isSymmetric(p->left, q->right)&&_isSymmetric(p->right, q->left); 】
4. 144. 二叉树的前序遍历
(温馨提示:这里的标题本身就是链接)
题目:
int BTreeSize(struct TreeNode* root)
{
return root==NULL?0:BTreeSize(root->left)+BTreeSize(root->right)+1;
}
void _preorder(struct TreeNode* root,int* a,int* pi)
{
if(root==NULL)
return ;
a[(*pi)++]=root->val;
_preorder(root->left,a,pi);
_preorder(root->right,a,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int size=BTreeSize(root);
int* a=(int*)malloc(sizeof(int)*size);
* returnSize=size;
int i=0;
_preorder(root,a,&i);
return a;
}
思路:需要返回一个数组a,只需要利用二叉树前序遍历函数preorder ,把打印这个值改成每次把这个值给数组a最后返回a就可以了(注意:为了让a能每次下标走下去,需要传i的地址进去才可以)并且用malloc给a开辟空间时,还需要知道a数组的大小,所以再利用一个计算二叉树节点个数的函数 BTreeSize (此函数详细讲解请见(155条消息) “二叉树遍历“详解 以及 二叉树的实现_beyond.myself的博客-优快云博客 中二.1.⑤)
5.94. 二叉树的中序遍历
此题跟第4题思路一模一样,这里就不过多赘述,4题会了这个题看看就行……
int TreeSize(struct TreeNode* root)
{
return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}
void _inorderTraversal(int* a,struct TreeNode* root,int* pi)
{
if(root==NULL)
return ;
_inorderTraversal(a, root->left,pi);
a[(*pi)++]=root->val;
_inorderTraversal(a, root->right,pi);
return;
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
int size=TreeSize(root);
* returnSize=size;
//printf("%d",size);
int* a=(int*)malloc(sizeof(int)*size);
int i=0;
_inorderTraversal(a,root,&i);
return a;
}
6.145. 二叉树的后序遍历
这个题跟第4,5一样,看看就行……
int TreeSize(struct TreeNode* root)
{
return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}
void _postorderTraversal(int* a,struct TreeNode* root,int* pi)
{
if(root==NULL)
return ;
_postorderTraversal(a, root->left,pi);
_postorderTraversal(a, root->right,pi);
a[(*pi)++]=root->val;
return;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
int size=TreeSize(root);
* returnSize=size;
//printf("%d",size);
int* a=(int*)malloc(sizeof(int)*size);
int i=0;
_postorderTraversal(a,root,&i);
return a;
}
7. 572. 另一棵树的子树
(温馨提示:这里的标题本身就是链接)
题目:
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p==NULL&&q==NULL)
return true;
if(p==NULL||q==NULL)
return false;
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);
}
当走到root节点为空时,肯定不包含subRoot,返回false;如果不为空就利用 判断两棵树是否相同函数 从已到的节点开始判断下面部分是否相同,相同就是包含subRoot,就返回true,不包含不能直接返回false,还得继续向下比较,所以说这里只要 isSameTree(root,subRoot) 成立一次就可以返回true,不成立继续向下找,只要包含成立一次就是返回true(所以用逻辑运算符 或|| ),不包含继续向下找,直到找到空节点就返回false。还可以写成下面的形式:
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p==NULL&&q==NULL)
return true;
if(p==NULL||q==NULL)
return false;
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;
return isSameTree(root,subRoot)||isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}
8.二叉树遍历_牛客题霸_牛客网 (nowcoder.com)
(温馨提示:这里的标题本身就是链接)
题目:
先把输入数据放入数组a,利用 CreatTree 函数,每创建一个节点,就把数组a中的数据放入,按前序遍历依次放入二叉树,边创建节点边放值,如果数组a中数据是‘#’就是空节点,返回NULL,会把NULL赋给这个节点同时也就结束递归,最后返回根节点tree到主函数中,再进行中序遍历打印即可
#include<stdio.h>
#include<stdlib.h>
typedef char BTDataType;
typedef struct BinaryTreeNode //创建二叉树结构体
{
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
BTDataType data;
}BTNode;
BTNode* CreatTree( char* a,int* pi)
{
if(a[*pi]=='#') //数据是‘#’就是空节点,返回NULL,同时也就结束递归
{
(*pi)++;
return NULL;
}
BTNode* tree=( BTNode*)malloc(sizeof( BTNode)); //边创建节点边放值
tree->data=a[(*pi)++]; //边创建节点边放值
tree->left=CreatTree( a, pi); //前序遍历的形式
tree->right=CreatTree( a, pi);
return tree;
}
void Inorder( BTNode* root) //中序遍历打印
{
if(root==NULL)
return ;
Inorder( root->left);
printf("%c ",root->data);
Inorder( root->right);
}
int main()
{
char a[100];
scanf("%s",a);
int i=0;
BTNode* tree=CreatTree(a,&i); //传&i 是使数组a下标可以正常走
Inorder(tree);
return 0;
}
9.226. 翻转二叉树
思路: 翻转二叉树只要将每一个节点的左右子树交换,一直到根节点的左右子树交换完就能达到翻转的效果。
过程:后序遍历,先找节点的左右节点后再交换,一直找到叶子的左右子树都是空节点,交换左右空节点后返回叶子节点,再把这个叶子和他的兄弟交换,逐层递归即可。
struct TreeNode* invertTree(struct TreeNode* root){
if(root==NULL)
return NULL;
struct TreeNode* left=invertTree( root->left);
struct TreeNode* right=invertTree( root->right);
root->left=right;
root->right=left;
return root;
}