当前位置: 首页 > news >正文

硅基计划3.0 学习总结 肆 二叉树 初版

在这里插入图片描述


文章目录

    • 一、树与性质
      • 1. 二叉树初识
      • 2. 树的表示
      • 3. 二叉树性质
    • 二、模拟实现二叉树
      • 1. 创建二叉树
      • 2.遍历
      • 3. 求节点个数
      • 4. 求叶子节点
      • 5. 求第K层节点个数
      • 6. 获取二叉树的高度(深度)
      • 7. 检测指定值是否存在于二叉树中


一、树与性质

1. 二叉树初识

二叉树指的是不存在>=2度数(子节点个数)的节点,分为左右子树,但是二叉树也有可能是空树

  • 完全二叉树:节点编号和节点一一对应,而且如果节点度数是偶数,不存在度为1的节点,如果是偶数,则一定存在一个度为1的节点,如下图所示
    image-20250727145324800

  • 满二叉树:每个节点除了最后一层以外的节点度数都为2,起始就是完全二叉树的特殊情况

2. 树的表示

树可以有多种表示方法,有双亲表示、孩子表示、孩子兄弟等,对于树的定义不过多细讲了

class Node{int value;Node firstChild;Node NextBrother;
}

image-20250727144311995

3. 二叉树性质

  1. 如果规定第一层的层数下标是一(意思就是不是用数组那种从零下标开始的叫法),那么第L层的最多有2k−12^k-12k1个节点
  2. 如果规定第一层的深度下标是一,那么深度为K的树节点总共有2k−12^k -12k1个节点
  3. 度为1的节点总比度为0的节点少一个

度数之和是度数为0的节点之和+度为1的节点之和+度为2的节点之和
而且边数比节点数少一个,利用这个性质,我们可以得到这个推论

  1. 具有n个节点的完全二叉树的深度为log⁡2(n+1)\log_2 (n+1)log2(n+1),结果向上取整(比如5.2–>6,5.8–>6)
  2. 含有n个节点的完全二叉树,如果i=0,那么它就是根节点,否则如果下标i>0,那么它的双亲下标就是(i-1)/2;同理如果2i+1<n,它的左子树(左孩子)下标是2i+1,否则不存在;同理如果2i+2>n,它的右子树(右孩子)下标是2i+2,否则不存在
    image-20250727151438449

二、模拟实现二叉树

二叉树的表示常用的是孩子表示法(一个节点的左右两个子节点)和孩子双亲表示法(除了左右两个子节点还包括自己)
接下来我们模拟实现最常用的孩子表示法

1. 创建二叉树

public class BinaryTree {static class TreeNode{int value;TreeNode left;//左孩子TreeNode right;//右孩子public TreeNode(int value) {this.value = value;}}public TreeNode creatNode(){TreeNode t1 = new TreeNode(15);TreeNode t2 = new TreeNode(22);TreeNode t3 = new TreeNode(34);TreeNode t4 = new TreeNode(56);TreeNode t5 = new TreeNode(77);TreeNode t6 = new TreeNode(99);//手动连接//左子树t1.left = t2;t1.right = t3;t2.left = t4;t2.right = t5;//右子树t3.left = t6;//返回头节点return t1;}//一些操作方法
}//测试类中
public class Test {BinaryTree binaryTree = new BinaryTree();BinaryTree.TreeNode root = binaryTree.creatNode();
}

2.遍历

image-20250727154448574
分为前序——根节点左孩子节点右孩子节点,中序——左跟右,后序——左右根,区别只是遍历的顺序不一样,他们的时间空间复杂度都是O(n)

    //前序遍历public void preOrder(TreeNode root){if(root == null){return;}System.out.print(root.value+" ");preOrder(root.left);preOrder(root.right);}//中序遍历public void inOrder(TreeNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.value+" ");inOrder(root.right);}//后序遍历public void pastOrder(TreeNode root){if(root == null){return;}pastOrder(root.left);pastOrder(root.right);System.out.print((root.value + " "));}//测试//前序遍历binaryTree.preOrder(root);System.out.println();//中序遍历binaryTree.inOrder(root);//后序遍历System.out.println();binaryTree.pastOrder(root);

这里我就拿前序遍历举例子
image-20250727161000360

3. 求节点个数

我们思路就是利用计数器,或者是子问题思路——左子树节点个数+有子树节点个数,他们的时间空间复杂度都是O(n)

ublic int count = 0;//计数器法则public void size(TreeNode root){if(root == null){return;}count++;size(root.left);size(root.right);}//子问题法则public int sizePlus(TreeNode root){if(root == null){return 0;}return sizePlus(root.left)+sizePlus(root.right)+1;}

4. 求叶子节点

我们的思路就是如果遇到了叶子节点就++,即当前节点的左右孩子节点都是空,时间空间复杂度都是O(n)

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);}

5. 求第K层节点个数

我们思路就是第K层是左子树的K-1层+右子树的K-1层
我们让K一直减减,直到K=1的时候,时间空间复杂度都是O(n)

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

6. 获取二叉树的高度(深度)

我们思路就是左右两个子树求出深度,谁的值比较大就取谁,最后再加上一(根节点),时间复杂度是O(n),空间复杂度是O(logN)

//求二叉树深度public int getHeight(TreeNode root){if(root == null){return 0;}return Math.max(getHeight(root.left),getHeight(root.right))+1;}

7. 检测指定值是否存在于二叉树中

我们的思路就是先判断根节点是不是我们要找的值,不是就递归,如果左子树没有,就去判断右子树,时间复杂度O(n),空间复杂度O(logN)

//检测值是否存在public TreeNode find(TreeNode root,int value){if(root == null){//终止情况return null;}if(root.value == value){//检测根节点情况return root;}TreeNode ret = find(root.left,value);//检查左子树if(ret != null){return ret;//找到了直接返回,下面语句不用进行了}ret = find(root.right,value);//左子树找不到,找右子树if(ret != null){return ret;//找到了直接返回}return null;//找不到语句到这里}

文章错误不可避免,期待您的指正,我们共同进步

Git码云仓库链接

END
http://www.dtcms.com/a/301426.html

相关文章:

  • [每周一更]-(第148期):使用 Go 进行网页抓取:Colly 与 Goquery 的对比与思路
  • QT---概览
  • 优化Linux高并发:文件描述符与端口范围的协同调优
  • SPSC无锁环形队列技术(C++)
  • FreeRTOS—空闲任务
  • 【Python系列】Flask 应用中的主动垃圾回收
  • idea打开后project窗口未显示项目名称的解决方案
  • LangGraph快速入门项目部署
  • C++ 中实现 `Task::WhenAll` 和 `Task::WhenAny` 的两种方案
  • 从0搭建YOLO目标检测系统:实战项目+完整流程+界面开发(附源码)
  • jenkins只能运行2个任务,提示:“等待下一个可用的执行器”
  • Redis C++客户端——命令使用
  • 实战演练1:实战演练之命名实体识别
  • Docker 的数据持久化-数据卷
  • (AC)架子鼓
  • 基于Java的KTV点歌系统的设计与实现
  • 【CF】Day112——杂题 (逆向思维 | 二分 + 贪心 | 单调队列优化DP | 二进制 + 前缀和 | 二分图判断 | 暴力枚举)
  • JavaEE--3.多线程
  • python-装饰器
  • 【ST表、倍增】P7167 [eJOI 2020] Fountain (Day1)
  • QT6 源,七章对话框与多窗体(15)多文档 MDI 窗体 QMdiArea 篇一:属性,公共成员函数,信号与槽函数
  • 多智能体架构
  • 《计算机组成原理与汇编语言程序设计》实验报告四 Debug及指令测试
  • setnonblocking函数用途和使用案例
  • 在本地环境中运行 ‘dom-distiller‘ GitHub 库的完整指南
  • OSPF路由协议 多区域
  • 【ESP32】无法找到: “${env:IDF_PATH}/components/“的路径报错问题以及CMAKE构建不成功问题
  • Cursor报错解决【持续更新中】
  • 金融科技中的远程开户、海外个人客户在线开户、企业客户远程开户
  • 深入解析Java运行机制与JVM内存模型