二叉树基础OJ练习

目录

习题一:查找值为x的节点,并返回节点指针。

习题二:相同的树

习题三:二叉树的前序遍历

习题四:另一棵树的子树

习题五:二叉树遍历


习题一:查找值为x的节点,并返回节点指针。

函数声明如下:BTNode* BinaryTreeFind(BTNode* root, int x);

以下图的树为例:
分析:先找到树的根,再找左子树,最后找右子树。

BTNode* BinaryTreeFind(BTNode* root, int x) {
	//第一种情况(当前节点为空)(终止条件)
	if (root == NULL) {
		return NULL;
	}
	//第二种情况(当前节点存储的数值为x,则返回当前节点)
	if (root->data == x) {
		return root;
	}
	//对左子树进行查找
	BTNode* lret = BinaryTreeFind(root->left, x);
	if (lret) {
		return lret;
	}
	//对右子树进行查找
	BTNode* rret= BinaryTreeFind(root->right, x);
	if (rret) {
		return rret;
	}
};

 通过画图对代码进行验证和检查:

 改正代码:

BTNode* BinaryTreeFind(BTNode* root, int x) {
	//第一种情况(当前节点为空)(终止条件)
	if (root == NULL) {
		return NULL;
	}
	//第二种情况(当前节点存储的数值为x,则返回当前节点)
	if (root->data == x) {
		return root;
	}
//代码运行到此处,表示节点存储的数值不为x,需要继续对其余节点(左子树、右子树)进行查找
	//对左子树进行查找
	BTNode* lret = BinaryTreeFind(root->left, x);
	if (lret) {
		return lret;
	}
	//对右子树进行查找
	BTNode* rret= BinaryTreeFind(root->right, x);
	if (rret) {
		return rret;
	}
    return NULL;
};

习题二:相同的树

https://leetcode.cn/problems/same-tree/submissions/

分析:根节点与根节点比较,左子树与左子树比较,右子树与右子树比较

//比较两个二叉树是否相同
bool isSameTree(struct BTNode* p, struct BTNode* q){
	//第一种情况:两个二叉树都为空
	if (p == NULL && q == NULL) {
		return true;
	}
	//第二种情况:一个二叉树为空且另一个不为空
	//又因为代码若运行到此处至少有一个二叉树不为空
	//则两个二叉树中至少有一个为空,返回错误
	if (p == NULL || q == NULL) {
		return false;
	}
	//对数据进行比较
	if (p->data != q->data) {
		return false;
	}
	//若代码运行到此处,则表示两个二叉树某一个根的节点值相同
	//此时,通过递归调用先对左子树进行比较,再对右子树进行比较
	//若左子树和右子树均返回true,则两个二叉树相同
	return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

【小总结】比较习题一和习题二,我们可以发现,两道习题在对于数值进行比较时,习题一是比较两个数值相同,习题二是比较两个数值不同。

这是为什么呢?

因为对于习题一,如果代码运行到数值比较结束处,表示当前节点数值与需要查找的数值不相同,因此需要对于左右子树使用递归调用进行查找。

对于习题二,如果码运行到数值比较结束处,表示两个二叉树当前节点的数值相同,因此需要对左右子树使用递归调用进行进一步的查找,因为某一个节点值的相同并不能代表两个二叉树是相同的。

所以,进行数值比较时,我们需要根据题目本身的要求比较。

习题三:二叉树的前序遍历

https://leetcode-cn.com/problems/binary-tree-preorder-traversal

//计算出树的节点的个数,便于开辟内存
 int TreeSize(struct TreeNode* root){
     return root==NULL? 0:
     TreeSize(root->left)+TreeSize(root->right)+1;
 }
 //进行前序遍历
 void preorder(struct TreeNode* root,int* a, int i){
     if(root==NULL)
        return;
    //后置加加,先使用再加加
    a[i++]=root->val;
    preorder(root->left,a,i);
    preorder(root->right,a,i);
    return;
 }
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize=TreeSize(root);
    int* a=(int*)malloc(*returnSize*sizeof(int));
    preorder(root,a,0);
    return a;

}

通过画图 ,检查错误:

 注意!对于每一次递归而言,i是一个局部变量,栈帧中保存的i值并不相同。

因此,我们使用传址的方式对上述代码加以改进。

//计算出树的节点的个数,便于开辟内存
 int TreeSize(struct TreeNode* root){
     return root==NULL? 0:
     TreeSize(root->left)+TreeSize(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);
    return;
 }
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize=TreeSize(root);
    int* a=(int*)malloc(*returnSize*sizeof(int));
    int i=0;
    preorder(root,a,&i);
    return a;

}

习题四:另一棵树的子树

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

思路:让左边树的每一棵子树都与右边的树进行比较

//比较两个二叉树是否相同
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);
}

习题五:二叉树遍历

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

先对示例通过前序遍历对二叉树进行图形还原

#include <stdio.h>
#include <stdlib.h>
struct TreeNode {
    struct TreeNode* left;
    struct TreeNode* right;
    char val;

};
//通过前序创建二叉树!
struct TreeNode* CreateTreeNode(char* a, int* pi) {
    if (a[*pi] == '#') {
        (*pi)++;
        return NULL;

    }
    //开始开辟动态内存
    struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    //将树的节点保存的值存放到数组中
    root->val = a[(*pi)++];
    //开始递归
    root->left = CreateTreeNode( a, pi);
    root->right = CreateTreeNode( a, pi);
    return root;
}

void InOrder(struct TreeNode* root){
    if(root==NULL)
        return ;
    else
       { InOrder(root->left);
        printf("%c ",root->val);
        InOrder(root->right);}
}

int main() {
    char a[1000];
    int i = 0;
    scanf("%s", a);
    struct TreeNode* root = CreateTreeNode(a, &i);
    InOrder(root);
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值