【数据结构】二叉树详解及基本操作

目录

1.树

2.二叉树的概念、相关知识(重点)

        2.1 概念

        2.2 二叉树的基本形态

         2.3两种特殊的二叉树

                2.3.1 满二叉树

                2.3.2 完全二叉树

         2.4 二叉树的性质

 3.二叉树的相关操作

        3.1二叉树的遍历

                3.1.1 前序遍历

                3.1.2 中序遍历

                3.1.3 后序遍历

        3.2 求二叉树的节点个数

        3.3 求叶子结点数

        3.4 求第k层的结点数


1.树

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

  • 一个特殊节点叫做根节点,没有前驱节点
  • 除了根节点以外,每个节点有且只有一个前驱节点,有0个或者多个后继节点
  • 树通常利用递归定义

结点的度:一个节点含有的子树个数称为该节点的度 ,例如上图A的度为4

树的度:一棵树中最大的节点的度称为树的度;上图中:树的度为4

叶子节点(终端节点):度为0的节点称为叶子结点;上图中:F、G、K、L、J

双亲节点(父节点):若一个节点有子节点,则称该节点为其子节点的父节点;上图中:A是B的父节点

孩子节点(子节点):一个节点含有的子树的根节点称为该节点的子节点; 上图中:B是A的孩子节点

节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推

树的高度或深度:树中节点的最大层次;如上图:树的个高度是4

以下内容只需了解皆即可:

非终端节点或分支节点:度不为0的节点; 如上图:B、C、D、E...等节点为分支节点
兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
森林:由m(m>=0)棵互不相交的树的集合称为森林

2.二叉树的概念、相关知识(重点)

        2.1 概念

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
二叉树的特点:
1. 每个结点最多有两棵子树,即二叉树不存在度大于 2 的结点。
2. 二叉树的子树有左右之分,其子树的次序不能颠倒,因此二叉树是有序树

        2.2 二叉树的基本形态

         2.3两种特殊的二叉树

                2.3.1 满二叉树

满二叉树: 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是2^k -1 ,则它就是满二叉树。

                2.3.2 完全二叉树

完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

简单理解:即一个二叉树的某个节点的子节点不可能出现只有有孩子的情况,有右孩子必定有左孩子,但有左孩子可以没有右孩子。 

         2.4 二叉树的性质

1.若规定根节点的层数为1,则一,棵非空二叉树的第i层上最多有2^(i-1)个节点

2.若规定只有根节点的二叉树的深度为1,则深度为k的二叉树的最大节点数是2^k -1(k>=0)

3.对任何一棵二叉树,如果其叶节点的个数为n0,度为2的非叶子结点个数为n2,则有n0=n2+1

4.具有n个节点的完全二叉树的深度为log2(n+1)上取整

5.对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有:

  • 若i>0,双亲序号:(i-1)/2; i=0时,i为根节点,无双亲节点
  • 若2i+1<n,左孩子序号:2i+1,否则无左孩子
  • 若2i+2<n,右孩子序号:2i+2,否则无右孩子

 3.二叉树的相关操作

        3.1二叉树的遍历

            遍历(Traversal)是指沿着某条搜索路线,一次对树中每个节点均做一次且仅做一次访问。遍历是二叉树上重要的操作之一,也是二叉树上进行其他操作的基础。

1.前序遍历(NLR):Preorder Traversal也称为先序遍历——访问根节点-->根的左子树-->根的右子树

2.中序遍历(LNR):Inorder Traversal ——根的左子树-->根节点-->根的右子树

3.后序遍历(LRN):Postorder Traversal ——根的左子树-->根的右子树-->根节点

不难看出,每种遍历的都可以划分为3个步骤,所以我们可以利用递归的方法来进行遍历,同时用递归的方法效率较高,容易理解。

        下面将用这棵树进行详细的讲解:

                3.1.1 前序遍历

 我们已经知道前序遍历的访问顺序是先访问根节点-->左子树-->右子树,所以上图中橙色的箭头表示访问顺序,就可以得出该树的前序遍历结果为   A-->B-->D-->E-->C-->F

        下面给出前序遍历的代码:

  public static void preorder(TreeNode root){
        if(root == null){
            return;
        }
        System.out.print(root.val+" ");
        preorder(root.left);
        preorder(root.right);
    }

                3.1.2 中序遍历

中序遍历顺序:左子树-->根节点-->右子树,所以优先遍历左子树的左孩子,因为B是D和E的父节点,所以不能先从B开始遍历,只能从D开始遍历

遍历结果为:D-->B-->E-->A-->F-->C

        实现代码:

    public static void inorder(TreeNode root){
        if(root == null){
            return;
        }
        inorder(root.left);
        System.out.print(root.val+" ");
        inorder(root.right);
    }

                3.1.3 后序遍历

 后序遍历的顺序:左子树-->右子树-->根节点

 遍历结果:D-->E-->B-->F-->C-->A

        实现代码:

public static void postOrder(TreeNode root){
        if(root == null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

        3.2 求二叉树的节点个数

节点个数可以拆分成两部分:左子树的结点数+右子树的结点数+1(根节点)

所以我们可以使用递归的方法求出节点的个数

        代码实现:

 public static int nodeCount(TreeNode root){
        if(root == null){
            return 0;
        }
        int leftCount = nodeCount(root.left);
        int rightCount = nodeCount(root.right);

        return leftCount+rightCount+1;
    }

        3.3 求叶子结点数

叶子结点即没有孩子节点,那么用代码表示就是root.left==null&&root.right==null,类似于求结点的个数,用左子树上所有的叶子结点数+右子树上所有的叶子结点数,利用递归可以解决

        代码实现:

 public static int leafCount(TreeNode root){
        if(root==null){
            return 0;
        }
        if(root.left==null && root.right==null){
            return 1;
        }
        int leftLeafCount = leafCount(root.left);
        int rightLeafCount = leafCount(root.right);

        return leftLeafCount+rightLeafCount;
    }

        3.4 求第k层的结点数

求第k层,我们可以把问题看做求第k-1层的左右孩子结点数之和,同时又可以将第k层看做k-2层的单独结点个数之和

         代码实现:

public static int calcLevelCount(TreeNode root,int k){
        if(root == null){
            return 0;
        }
        if(k == 1){
            return 1;
        }
        int leftNodeCount = calcLevelCount(root.left,k-1);
        int rightNodeCount = calcLevelCount(root.right,k-1);

        return leftNodeCount+rightNodeCount;
    }

 

  • 12
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值