二叉树的核心概念与遍历实现(基础详解版)

文章目录

一、树的基本概念

树是一种非线性结构(节点之间的关系是一对多),节点为0的树称为空树。
节点的度:一个节点含有的子树的个数。例如:下图D节点的度是2。
树的度:树中节点最大度称为数的度。例如:下图树的度是3。
叶子节点或终端节点:度为0的节点。例如:E,F,G,H,I,J都是叶子节点。
双亲节点或父节点:若一个节点含有子节点,则称这个节点为子节点的父节点。例如:B节点含有F,E.G,B节点为E,F,G的父节点。
孩子节点:是指某个节点的子树的根节点。例如:A的孩子节点是B,C,D。
根节点:一颗树中没有双亲的节点。例如:A为这棵树的根节点。
节点的层次:一棵树中,根为第一层,根的子节点为第二层,以此类推。
树的高度或深度:树中节点的最大层次。如下图树的高度为3。
非终端节点或分支节点:度不为0的节点。
兄弟节点:具有相同父节点的节点称为兄弟节点。
森林:由m(m>=0)棵树组成的集合称为森林。

二、二叉树(重点)

2.1二叉树的概念

二叉树是节点的度不大于2的的有序树

二叉树的基本形态有5种:

1.空二叉树

2.只有一个根节点

3.根节点只有左子树

4.根节点只有右子树

5.根节点既有左子树,又有右子树。

2.2两种特殊的二叉树

1.满二叉树:一颗二叉树中每一层节点都达到最大值,则这棵树就是满二叉树。

2.完全二叉树:在满二叉树的基础上,去掉右下的一些连续叶子节点所形成的树。

满二叉树是特殊的完全二叉树。

2.3二叉树的性质(重要)

2.4二叉树的存储

二叉树的存储结构为:顺序结构和类似链表的链式存储(包括孩子表示法,双亲表示法,孩子双亲表示法)。
顺序存储结构适用于:完全二叉树和满二叉树,因为完全二叉树和满二叉树的节点符合自上而下、自左向右排列,因此采用顺序存储比较合适,这样可以最大程度的节省空间,又能利用数组的下标确定节点在二叉树的位置。但对于一般的二叉树采用顺序存储会浪费很多空间。

链式存储:由于顺序存储的空间利用率较低,所以二叉树一般采用链式存储。

三、二叉树的遍历

以下三种遍历基于我画的这棵二叉树。

3.1先序遍历的文字和图示遍历表示

先序遍历:先遍历根节点,再遍历左子树,最后遍历右子树。每颗树都要满足根左右。

(可以不看较为啰嗦,下面有代码和图示实现遍历)

先走到A是根节点,打印A

再遍历A的左子树,遇到B节点, B是子树根节点,打印B

再遍历B的左子树,遇到D节点,D是子树的根节点,打印D

再遍历D的左子树,为空,返回到D节点

再遍历D的右子树,为空,返回到D节点

D节点返回到B节点,遍历B的右子树,E为右子树的根节点,打印E节点。

遍历E节点的左子树,左子树为空,返回到E节点。

遍历E节点的右子树,子树的根节点为H,打印H

遍历H节点的左子树为空,返回到H节点

遍历H节点的右子树为空,返回到H节点

H节点左右子树遍历完,返回到E节点。

E节点左右子树遍历完,返回到B节点。

B节点左右子树遍历完,返回到A 节点,继续遍历A的右子树。

C是子树的根节点,打印C节点。

遍历C节点的左子树,F是子树的根节点,打印F节点

遍历F节点的左子树为空,返回到F节点

遍历F节点的右子树为空,返回到F节点

F节点左右子树遍历完,返回到C节点,遍历C节点的右子树

右子树的根节点的是G,打印G节点

遍历G节点的左子树为空,返回到G节点

遍历G节点的右子树为空,返回到G节点

G节点左右子树遍历完,返回到C节点。

C节点的左右子树遍历完,C节点返回到A节点。

以上就是前序遍历的递归过程。

所以先序遍历的顺序是:ABDEHCFG。

3.1.1先序遍历的代码递归实现

BinaryTree类

java 复制代码
public class BinaryTree {
    static class TreeNode{
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }
    public TreeNode createBinaryTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode H = new TreeNode('H');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        A.left = B;
        B.left = D;
        B.right = E;
        E.right = H;
        A.right = C;
        C.left = F;
        C.right = G;
        return A;//返回根节点
    }
    public void preOrder(TreeNode root){
        if(root == null){
            return;
        }
        //遍历根
        System.out.print(root.val+" ");
        //遍历左子树
        preOrder(root.left);
        preOrder(root.right);
    }

}

Test测试类

java 复制代码
public class Test {
    public static void main(String[] args) {
     BinaryTree binaryTree = new BinaryTree();
     BinaryTree.TreeNode root = binaryTree.createBinaryTree();
        System.out.println("根节点:"+root.val);
        binaryTree.preOrder(root);
    }
}

打印结果为:

3.2中序遍历的文字和图示遍历表示

中序遍历:先遍历左子树,再遍历根节点,最后遍历右子树。每一棵树都要按照左根右遍历。

先从根节点进入,不打印根,遍历根的左子树,走到B节点,不打印B节点,遍历B这棵子树的左子树,走到D节点,遍历D的左子树为空返回到D节点,打印D节点,遍历D节点的右子树,为空返回到D节点,D节点遍历完返回到B节点,打印B节点,遍历B节点的右子树...接下来按照这个方式继续遍历即可得到这棵树的中序遍历。

所以中序遍历的顺序是:DBEHAFCG。

3.2.1中序遍历的代码递归实现

BinaryTree类

java 复制代码
public class BinaryTree {
    static class TreeNode{
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }
    public TreeNode createBinaryTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode H = new TreeNode('H');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        A.left = B;
        B.left = D;
        B.right = E;
        E.right = H;
        A.right = C;
        C.left = F;
        C.right = G;
        return A;//返回根节点
    }
    public void inOrder(TreeNode root){
        if(root == null){
            return;
        }
        //先遍历左子树
        inOrder(root.left);
        //遍历根
        System.out.print(root.val+" ");
        //遍历右子树
        inOrder(root.right);
    }
}

Test测试类

java 复制代码
public class Test {
    public static void main(String[] args) {
     BinaryTree binaryTree = new BinaryTree();
     BinaryTree.TreeNode root = binaryTree.createBinaryTree();
        System.out.println("根节点:"+root.val);
        binaryTree.inOrder(root);
   }
}

打印结果

3.3后序遍历的文字和图示遍历表示

后序遍历:先遍历左子树,再遍历右子树,最后遍历根节点。每一棵树都要按照左右根遍历。

所以后序遍历的顺序是:DHEBFGCA。

3.3.1后序遍历的代码递归实现

BinaryTree类

java 复制代码
public class BinaryTree {
    static class TreeNode{
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }
    public TreeNode createBinaryTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode H = new TreeNode('H');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        A.left = B;
        B.left = D;
        B.right = E;
        E.right = H;
        A.right = C;
        C.left = F;
        C.right = G;
        return A;//返回根节点
    }
    public  void postOrder(TreeNode root){
        if(root == null){
            return;
        }
        //先遍历左子树
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

}

Test测试类

java 复制代码
public class Test {
    public static void main(String[] args) {
     BinaryTree binaryTree = new BinaryTree();
     BinaryTree.TreeNode root = binaryTree.createBinaryTree();
        System.out.println("根节点:"+root.val);
        binaryTree.postOrder(root);
   }
}

打印结果

四、二叉树的基本操作(代码实现)

4.1获取树中的节点的个数

java 复制代码
public int size(TreeNode root){
        //总节点个数=左子树的节点个数+右子树的节点个数+1(根节点)
        if(root == null){
            return 0;
        }
        return size(root.left)+size(root.right)+1;

    }

4.2获取树中叶子节点的个数

java 复制代码
 public 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);

    }

4.3获取树中第K层节点的个数

java 复制代码
 public int getKLevelNodeCount(TreeNode root,int k){
        //获取第K层的节点个数,root左树的第k-1层+root右树的第k-1层,root也算一层
        if(root == null){
            return 0;
        }
        if(k == 1){
            return 1;
        }
        return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
    }

4.4获取二叉树的高度

java 复制代码
public int getHeight(TreeNode root){
      //左子树的高度和右子树的高度的最大值+1;
      if(root == null){
          return 0;
      }
      return Math.max(getHeight(root.left),getHeight(root.right))+1;
  }

4.5检测val字符是否存在

java 复制代码
 public TreeNode find(TreeNode root,char val) {
     if (root == null) {
         return root;
     }
     if (root.val == val) {
         return root;

     }
     BinaryTree.TreeNode left = find(root.left, val);
     if (left != null) {     //找到了
         return left;
     }
     BinaryTree.TreeNode right = find(root.right, val);
     if (right != null) {
         return right;

     }
     return null;  //没找到
 }
相关推荐
im_AMBER1 小时前
数据结构 12 图
数据结构·笔记·学习·算法·深度优先
程序员-周李斌1 小时前
LinkedList 源码深度分析(基于 JDK 8)
java·开发语言·数据结构·list
咫尺的梦想0071 小时前
链表——删除链表的倒数第 N 个结点
数据结构·链表
梁bk1 小时前
Redis底层数据结构 -- ziplist, quicklist, skiplist
数据结构·数据库·redis
myw0712052 小时前
湘大头歌程-Ride to Office练习笔记
c语言·数据结构·笔记·算法
H_BB2 小时前
算法详解:滑动窗口机制
数据结构·c++·算法·滑动窗口
淀粉肠kk2 小时前
【C++】封装红黑树实现Mymap和Myset
数据结构·c++
坚持就完事了2 小时前
十大排序算法
数据结构·算法·排序算法
小白程序员成长日记3 小时前
2025.11.29 力扣每日一题
数据结构·算法·leetcode