二叉树(练习题)

日升时奋斗,日落时自省 

目录

一、二叉树练习

习题一

 习题二

 习题三

习题三(简易思路)(复杂度O(​编辑))

 习题四

习题五


一、二叉树练习

习题一

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

 相同的两个树,认为结构以及数值都是相同的树

条件解析:

(1)判断空树

(2)结构相同:都存在左子树或者存在右子树

(3)数值相同:在结构相同的基础上确定其相同结构位置的数值也相同

 

public boolean isSameTree(TreeNode p, TreeNode q) {
        //首先判断空
        //然后就是判断结构是否相同
        //在判断数值是否相同
        if (p == null && q == null) {   //判断为空是也算相同
            return true;
        }
        if (p == null && q != null || p != null && p == null) {   //一颗树为空,另一颗树不为空
            return false;
        }
        if (p.val != q.val) {       //当前树结构是是相同,但是值不相同,也不是相同的树
            return false;
        }
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);   //同时遍历树的左边,右边
    }

 习题二

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

 判断另一颗树的子树,上一题已经判断了相同树的代码,改题可以将上一题的代码作为这题的子方法

条件解析:

(1)两颗树是否相同

(2)左子树是否与该树相同

(3)右子树是否与该树相同

(4)前面三个条件实现后会有问题,是null地址异常,需要在开始的判断空

 

 //判断两课树是否相同
    public boolean isSameTree(TreeNode p, TreeNode q) {
        //首先判断空
        //然后就是判断结构是否相同
        //在判断数值是否相同
        if (p == null && q == null) {   //判断为空是也算相同
            return true;
        }
        if (p == null && q != null || p != null && p == null) {   //一颗树为空,另一颗树不为空
            return false;
        }
        if (p.val != q.val) {       //当前树结构是是相同,但是值不相同,也不是相同的树
            return false;
        }
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);   //同时遍历树的左边,右边
    }
    //判断另一颗树的子树
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root==null){   //判断空时为了防止root.left的null异常
            return false;
        }
        //第一种情况就是两树都是相同的
        if(isSameTree(root,subRoot)){    //判断两树是否相同
            return true;
        }
        if(isSubtree(root.left,subRoot)){    //两树不相同的情况下,判断左子树与该树相同
            return true; 
        }
        if(isSubtree(root.right,subRoot)){   //左子树不能找到相同就是找右子树是否存在相同
            return  true;
        }
        return false;
    }

 习题三

110. 平衡二叉树 - 力扣(LeetCode)

 什么是平衡二叉树:每个节点的左子树与右子树的高度差<2

条件解析:

(1)计算左子树高度

(2)计算右子树高度

(3)左子树高度-右子树高度<=1

 特殊情况:

public boolean isBalanced(TreeNode root) {
        if(root==null){
            return true;
        }
        return getMax(root)>=0;   //如果高度差大于等于零就是平衡二叉树
    }
    public int getMax(TreeNode root){
        if(root==null){   //判空就是0
            return 0;
        }
        int leftheight=getMax(root.left);  //计算当前左子树的高度
        int rightheight=getMax(root.right);  //当前右子树的高度
        if(Math.abs(leftheight-rightheight)<=1&&leftheight>=0&&rightheight>=0){
            return Math.max(leftheight,rightheight)+1;          //高度左右子树相减之后还有一个根节点的高度
        }else {
            return -1;   //如果没有<=1就会为-1
        }
    }

习题三(简易思路)(复杂度O(n^{2}))

条件解析:

(1)写一个子方法计算树的高度

(2)在平衡二叉树的方法中调用树高度方法 求当前左子树高度,当前右子树高度

(3)左右子树高度差小于等于1,递归左右子树同时都满足平衡

public boolean isBalanced1(TreeNode root) {
        if(root==null){
            return true;
        }
        int leftside=getMax(root.left);  //当前左子树的高度
        int rightside=getMax(root.right);  //当前右子树的高度
        if(Math.abs(leftside-rightside)<=1&&isBalanced(root.left)&&isBalanced(root.right)){   //满足当前根节点的左子树与右子树的高度相减小于等于1左子树与右子树都是平衡的
            return true;
        }
        return false;
    }
    public int getMax1(TreeNode root){   //计算树的高度
        if(root==null){
            return 0;
        }
        int leftHeight=getMax(root.left);
        int rightHeight=getMax(root.right);
        return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
    }

 习题四

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

 条件解释:

(1)将一颗树分为两颗树来遍历

(2)一颗子树左遍历,另一颗子树右遍历

(3)涉及机构相同

(4)数值相同

//两颗子树是否完全对称
    public boolean isSymmetric(TreeNode root) {   //是不是对称树
        if(root==null){
            return true;
        }
        return isSymmetricChild(root.left,root.right);   //两个子树是否完全对称
    }
    private boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree) {
        if(leftTree==null&&rightTree==null){  //两颗树都是空树
            return true;
        }
        if(leftTree!=null&&rightTree==null||leftTree==null&&rightTree!=null){  //两树结构不同
            return false;
        }
        if(leftTree.val!=rightTree.val){   //两树结构相同,但是值不相同
            return false;
        }
        return isSymmetricChild(leftTree.left, rightTree.right)&&isSymmetricChild(leftTree.right,rightTree.left);   //对称方向遍历
    }

习题五

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

先进行先序遍历的二叉树 后进行中序遍历 

条件解释:

 (1)可以先写一个中序遍历的方法

 (2)获取字符串中每个字节,如果不是#的话,就可以进行新节点的建立

 (3)每次字符串下标向后移动

 (4)如果为#的话向后移动跳过

public static void main(String[] args) {
        Main s=new Main();
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String str=in.nextLine();
            TreeNode root=creatTree(str);
            s.inorder(root);
        }
    }
public  void inOrder1(TreeNode root){   //一个中序遍历
        if(root==null){
            return ;
        }
        inOrder1(root.left);
        System.out.print(root.val+" ");
        inOrder1(root.right);
    }
    private static int i=0;
    private static TreeNode creatTree(String str){   //创建一个新的根节点
        TreeNode rootnew=null;
        if(str.charAt(i)!='#'){  //只要不等于#就是加入
            rootnew=new TreeNode(str.charAt(i));   //新建一个节点
            i++;   //字符串加加
            rootnew.left=creatTree(str);  //先序遍历,先网左边放
            rootnew.right=creatTree(str);
        }else{
            i++;   //遇见#跳过
        }
        return rootnew; //最终返回当前根节点
    }

(1)非递归定义 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大树分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗树,由此我们可以给出树的递归定义。 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其中每个集合Ti(0≤i<m)本身又是一棵树,称为根的子树(subtree)。 2、掌握树的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、树的高度 (4) 边、路径 (5) 无序树、有序树 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子树的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子树或者右子树,亦或者左、右子树皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。
### 关于线索二叉树练习题 #### 中序线索二叉树的特点 中序线索二叉树通过在每个节点增加两个指针域 `ltag` 和 `rtag` 来实现,分别表示该节点是否有前驱和后继。如果某个节点有左孩子,则它的 `lchild` 指向左孩子;如果没有左孩子,则指向其前驱节点。同样地,如果有右孩子,则 `rchild` 指向右孩子;如果没有右孩子,则指向其后继节点[^2]。 #### 寻找特定节点的前驱与后继 在一个中序线索二叉树中,对于任意节点 X 的前驱可以通过以下方式找到: - 如果节点 X 存在左子树,则前驱为左子树中的最右侧节点(即沿着左子树一直往右走直到无法再继续)。 - 若不存在左子树,则前驱为其父节点链上的最近祖先节点,且该祖先节点的右子树包含当前节点[^5]。 #### 构造一棵二叉树并对其进行线索化处理 假设已知某棵二叉树的先序遍历序列 `[A, B, D, E, C, F]` 及其中序遍历序列 `[D, B, E, A, C, F]`,则可以根据这些信息重建原始二叉树,并进一步将其转化为中序线索二叉树[^4]。 以下是基于 Python 实现的一个简单例子来展示如何构建这样的二叉树以及完成中序线索化的操作: ```python class TreeNode: def __init__(self, val=0, lchild=None, rchild=None, ltag=False, rtag=False): self.val = val self.lchild = lchild self.rchild = rchild self.ltag = ltag self.rtag = rtag def build_tree(preorder, inorder): if not preorder or not inorder: return None root_val = preorder[0] root_index_in_inorder = inorder.index(root_val) left_inorder = inorder[:root_index_in_inorder] right_inorder = inorder[root_index_in_inorder + 1:] left_preorder = preorder[1:len(left_inorder)+1] right_preorder = preorder[len(left_inorder)+1:] node = TreeNode(val=root_val) node.lchild = build_tree(left_preorder, left_inorder) node.rchild = build_tree(right_preorder, right_inorder) return node def threaded_binary_tree(root): pre_node = None def thread(node): nonlocal pre_node if not node: return thread(node.lchild) if not node.lchild: node.lchild = pre_node node.ltag = True if pre_node and not pre_node.rchild: pre_node.rchild = node pre_node.rtag = True pre_node = node thread(node.rchild) thread(root) # Example Usage preorder = ['A', 'B', 'D', 'E', 'C', 'F'] inorder = ['D', 'B', 'E', 'A', 'C', 'F'] tree_root = build_tree(preorder, inorder) threaded_binary_tree(tree_root) ``` 上述代码展示了如何利用给定的先序和中序遍历来创建一颗完整的二叉树,并对该二叉树执行中序线索化过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值