首页 > 其他分享 >二叉树的学习

二叉树的学习

时间:2024-08-10 13:27:56浏览次数:9  
标签:结点 TreeNode 学习 二叉树 return null root

目录

树形结构

树中的概念

树的表示方法

二叉树

二叉树的重要性质

二叉树的存储

遍历

中序遍历

后续遍历

层序遍历

创建二叉树

二叉树的遍历

获取树中节点个数

获取叶子节点的个数

获取第k层节点个数

获取二叉树的高度

检测val元素是否存在

二叉树相关题目

检查两棵树是否相同

另一棵树的子树

反转二叉树


树形结构

一棵树是由若干个不相交的子树组成的

树形结构中,子树之间不能有交集,否则就不是树形结构

子树是不相交的

除了根结点外,每个结点有且仅有一个父结点

一棵N个结点的树有N-1条边。

树中的概念

结点的度 :一个结点含有子树的个数称为该结点的度 树的度 :一棵树中,所有结点度的最大值称为树的度 叶子结点或终端结点 :度为 0 的结点称为叶结点 双亲结点或父结点 :若一个结点含有子结点,则这个结点称为其子结点的父结点 孩子结点或子结点 :一个结点含有的子树的根结点称为该结点的子结点 根结点 :一棵树中,没有双亲结点的结点 结点的层次 :从根开始定义起,根为第 1 层,根的子结点为第 2 层,以此类推 树的高度或深度 :树中结点的最大层次 树的以下概念只需了解,在看书时只要知道是什么意思即可: 非终端结点或分支结点 :度不为 0 的结点 兄弟结点 :具有相同父结点的结点互称为兄弟结点 堂兄弟结点 :双亲在同一层的结点互为堂兄弟 结点的祖先 :从根到该结点所经分支上的所有结点 子孙 :以某结点为根的子树中任一结点都称为该结点的子孙 森林 :由 m ( m>=0 )棵互不相交的树组成的集合称为森林

树的表示方法

孩子双亲表示法 class Node { int value ; // 树中存储的数据 Node firstChild ; // 第一个孩子引用 Node nextBrother ; // 下一个兄弟引用,同深度的兄弟 }

二叉树

一棵二叉树是结点的一个有限集合,该集合: 1. 或者为空 2. 或者是由 一个根节 点加上两棵别称为 左子树右子树 的二叉树组成。 从上图可以看出: 1. 二叉树不存在度大于 2 的结点 2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树 一颗树如果是二叉树,那么他每棵树都是二叉树 每个节点度<=2 二叉树都是由以下几种情况复合而成 1. 满二叉树 : 一棵二叉树,如果 每层的结点数都达到最大值,则这棵二叉树就是满二叉树 。也就是说, 如果一棵 二叉树的层数为 K ,且结点总数是 2^{k}-1,则它就是满二叉树 。 2. 完全二叉树 : 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为 K 的,有 n 个结点的二叉树,当且仅当其每一个结点都与深度为K 的满二叉树中编号从 0 至 n-1 的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。 节点编号: 从上到下,从左到右,依次存放。
二叉树的重要性质
二叉树的性质 1. 若规定 根结点的层数为 1 ,则一棵 非空二叉树的第 i 层上最多有2^{i-1} (i>0) 个结点 2. 若规定只有 根结点的二叉树的深度为 1 ,则 深度为 K 的二叉树的最大结点数是2^{k}-1(k>=0) 3. 对任何一棵二叉树 , 如果其 叶结点个数为 n0, 度为 2 的非叶结点个数为 n2, 则有 n0 n2 1 任何一颗二叉树 叶子节点的个数永远比度为2的节点个数多1个 4. 具有 n 个结点的完全二叉树的深度 k \log_{2}{(n+1)}上取整 5. 对于具有 n 个结点的完全二叉树 ,如果按照 从上至下从左至右的顺序对所有节点从 0 开始编号 ,则对于 序号为 i 的结点有 : 若 i>0 , 双亲序号: (i-1)/2i=0 i 为根结点编号 ,无双亲结点 2i+1<n ,左孩子序号: 2i+1 ,否则无左孩子 2i+2<n ,右孩子序号: 2i+2 ,否则无右孩子

二叉树的存储

// 孩子表示法 class Node { int val ; // 数据域 Node left ; // 左孩子的引用,常常代表左孩子为根的整棵左子树 Node right ; // 右孩子的引用,常常代表右孩子为根的整棵右子树 } // 孩子双亲表示法 class Node { int val ; // 数据域 Node left ; // 左孩子的引用,常常代表左孩子为根的整棵左子树 Node right ; // 右孩子的引用,常常代表右孩子为根的整棵右子树 Node parent ; // 当前节点的根节点 }
遍历

指的是沿着某条路线遍历

前序遍历

前序是指根在前

先根,再左子树,再右子树

当左子树遍历完时,返回时遍历右子树,直到遍历到根

中序遍历

后续遍历

层序遍历

从上到下,从左到右依次遍历

创建二叉树

二叉树的遍历
public class BinaryTree {
    static class TreeNode{
        //孩子表示法
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val){
            this.val=val;
        }
    }
    //public TreeNode root;
    //创建一棵二叉树,创建成功后,返回根节点
    public TreeNode createTree(){
        TreeNode A=new TreeNode('A');
        TreeNode B=new TreeNode('B');
        TreeNode C=new TreeNode('C');
        TreeNode D=new TreeNode('D');
        TreeNode E=new TreeNode('E');
        TreeNode F=new TreeNode('F');
        TreeNode G=new TreeNode('G');
        TreeNode H=new TreeNode('H');

        A.left=B;
        A.right=C;
        B.left=D;
        B.right=E;
        C.left=F;
        C.right=G;
        E.right=H;

        return A;

    }
    //前序遍历
    void preOrder(TreeNode root){

        if (root==null){
            return;
        }
        System.out.println(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    //中序遍历
    void inOrder(TreeNode root){
        if (root==null){
            return;
        }

        preOrder(root.left);
        System.out.println(root.val+" ");
        preOrder(root.right);

    }

    //后续遍历
    void postOrder(TreeNode root){
        if (root==null){
            return;
        }

        preOrder(root.left);

        preOrder(root.right);
        System.out.println(root.val+" ");

    }
    //把前序遍历的结果储存到list当中
    List<Integer> ret=new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root){
        if (root==null){
            return null;
        }

        ret.add(root.val);
        preOrder(root.left);

        preOrder(root.right);
        return ret;
    }

}
获取树中节点个数

前序遍历还是中序遍历,只要遍历到节点就让计数器++

 //获取树中节点的个数
    public int nodeSize;
    int size(TreeNode root){
        if (root==null){
            return 0;
        }
        nodeSize++;
        size(root.left);
        size(root.right);
        return nodeSize;
    }
    int size2(TreeNode root){
        if (root==null){
            return 0;
        }
        return size2(root.left)+size2(root.right)+1;
    }
获取叶子节点的个数

    //获取叶子节点个数
    //不用递归
    public int leafSize;
    int getLeafNodeCount1(TreeNode root){
        if (root==null){
            return 0;
        }
        if (root.left==null&&root.right==null){
            leafSize++;
        }
        getLeafNodeCount1(root.left);
        getLeafNodeCount1(root.right);

        return leafSize;

    }
    int getLeafNodeCount(TreeNode root){
        if (root==null){
            return 0;
        }
        if (root.left==null&&root.right==null){
            return 1;
        }

        return getLeafNodeCount(root.left)+getLeafNodeCount(root.right);

    }
获取第k层节点个数
  // 获取第K层节点的个数
    int getKLevelNodeCount(TreeNode root,int k) {
        if (root==null){
            return 0;
        }
        if (k==1){
            return 1;
        }
        return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);

    }
获取二叉树的高度

左子树的高度,与右子树的高度的最大值加1

// 获取二叉树的高度
    int getHeight(TreeNode root){
        if (root==null){
            return 0;
        }
        int leftHeight=getHeight(root.left);
        int rightHeight=getHeight(root.right);

        return leftHeight>rightHeight?leftHeight+1:rightHeight+1;

    }
检测val元素是否存在
// 检测值为value的元素是否存在
    TreeNode find(TreeNode root, int val) {

        if (root==null){
            return null;
        }
        if (root.val==val){
            return root;
        }
        TreeNode ret1=find(root.left,val);
        if (ret1!=null){
            return ret1;
        }
        TreeNode ret2=find(root.right,val);
        if (ret2!=null){
            return ret2;
        }
        return null;

    }

二叉树相关题目

检查两棵树是否相同

 public boolean isSameTree(TreeNode p, TreeNode q) {
        if ((p == null && q != null) || (p != null && q == null)) {
            return false;
        }

        //上述代码走完之后,要么两个都为空,要么两个都不为空
        if (p == null && q == null) {
            return true;
        }
        //代码走到这里 两个都不为空
        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||subRoot==null){
            return false;
        }
        //1、是不是根节点相同
        if (isSameTree(root,subRoot)){
            return true;
        }
        //2、判断是不是root左子树
        if (isSubtree(root.left,subRoot)){
            return true;
        }
        //3、右子树
        if (isSubtree(root.right,subRoot)){
            return true;
        }
        //4、返回
        return false;
    }

    public boolean isSameTree(TreeNode p, TreeNode q) {
        if ((p == null && q != null) || (p != null && q == null)) {
            return false;
        }

        //上述代码走完之后,要么两个都为空,要么两个都不为空
        if (p == null && q == null) {
            return true;
        }
        //代码走到这里 两个都不为空
        if (p.val != q.val) {
            return false;
        }
        return isSameTree(p.left, q.left)
                && isSameTree(p.right, q.right);
    }
反转二叉树

public TreeNode invertTree(TreeNode root) {

        if (root==null){
            return null;
        }
        if (root.left==null&&root.right==null){
            return root;
        }
        TreeNode tmp=root.left;
        root.left=root.right;
        root.right=tmp;
        
        invertTree(root.left);
        invertTree(root.right);
        

        return root;
    }

标签:结点,TreeNode,学习,二叉树,return,null,root
From: https://blog.csdn.net/m0_56198792/article/details/141025419

相关文章

  • 大数据学习必备前置知识——Linux 之shell
    大数据学习必备前置知识——Linux之shell大家好!在为您带来精彩的技术干货之前,先给您推荐一个我精心运营的公众号[大数据深度洞察]。在这里,您将获取更多独家的技术分享、实用案例以及行业前沿资讯。亲爱的读者们,当您准备开启这篇充满价值的技术文章之旅时,不妨先关注我的公......
  • 机器学习笔记:序列到序列学习[详细解释]
    介绍本节我们使用两个循环神经网络的编码器和解码器,并将其应用于序列到序列(sequencetosequence,seq2seq)类的学习任务。遵循编码器-解码器架构的设计原则,循环神经网络编码器使用长度可变的序列作为输入,将其转换为固定形状的隐状态。换言之,输入序列的信息被编码到循环神经网......
  • 第六周学习报告
    又经过了一周的学习,今天对本周学习进行总结本周学习了Java面向对象进阶内容抽象类和抽象方法抽象类使用abstract关键字声明的类被称为抽象类。抽象类不能被实例化。抽象方法使用abstract关键字声明的方法被称为抽象方法。抽象方法没有方法体,即大括号{}内没有代码实现。抽象......
  • 8.10第四周周六学习总结
    1vj团队12补题不错的一个题解https://blog.fishze.com/archives/3011)字符串变化(模拟+找规律)题目:给定一个字符串,给定一个特定操作方式:该字符串前半段+该字符串自己+该字符串后半段求next(每一个字符向后移动一个),组成一个新字符串,求经过10^100次这样的操作后,......
  • 2-SAT 学习笔记
    2-SAT用于求解布尔方程组,其中每个方程最多含有两个变量,方程的形式为\((a∨b)=1\),即式子\(a\)为真或式子\(b\)为真。求解的方法是根据逻辑关系式建图,然后求强联通子图,每一个强联通子图的答案都是一样的。建图:这里以模版题为例:题意:给定若干个需要满足的条件,其形式为\(a,1......
  • 大一暑假学习记录6
    这一周我基本完成了刘立嘉老师布置的暑假作业,其中通讯录的录入与显示,整数分解为若干项之和是我认为最难做的题目,前者的难点是sample有查询越界、最大N,反复查询同一记录等等。后者则是样例等价,多行输出难以解决。于是我又重新学习了结构体部分的内容,定义了Contact结构体来存储......
  • 学生Java学习路程-6
    ok,到了一周一次的总结时刻,我大致会有下面几个方面的论述:1.这周学习了Java的那些东西2.这周遇到了什么苦难3.未来是否需要改进方法等几个方面阐述我的学习路程。复习面向对象数组数组的三种初始化方法:默认,静态,动态引用类型Man放入数组中的测试代码数组的拷贝使用规范使......
  • 二叉树——6.平衡二叉树
    力扣题目链接给定一个二叉树,判断它是否是高度平衡的二叉树。示例:TureFalse首先做这道题目前要明白什么是平衡二叉树?平衡二叉树的定义是,对于二叉树的每一个节点,它的左子树和右子树的高度差不超过1。结合示例中的两个例子理解平衡二叉树的定义。完整代码如下:#Definition......
  • 爆火下28万次!MIT最新-理解深度学习
        最近疯传的-理解深度学习-高达28万次,被认为可能。涵盖了深度学习从基础到高级各个方面的内容,包括基本概念、监督学习、强化学习、线性回归、神经网络、扩散模型等等。全面系统地机器学习的基础概念和深度学习的多种模型,还包括最新的Transformer和图神经网络。 免......
  • 【ACM出版,见刊检索快速稳定】第四届物联网与机器学习国际学术会议(IoTML 2024,8月23-25)
    2024年第四届物联网与机器学习国际学术会议(IoTML2024)将于2024年8月23-25日在中国南昌召开。会议将围绕着物联网和机器学习开展,探讨本领域发展所面临的关键性挑战问题和研究方向,以期推动该领域理论、技术在高校和企业的发展和应用,为专注于该研究领域的创新学者、工程师和......