树与二叉树
前言:
树这个结构想必在日常生活中很常见到,而现在要介绍的是一种独特的数据结构--二叉树。
1.树
(1)定义:
是一种非线性结构,有一个特殊的节点叫做根节点,树没有前驱节点;树是递归定义的;树形结构中子树不能有交集,否则就不是树形结构。

(2)树相关重要概念:(如上图)
节点的度:一个节点含有的子树的个数。eg:A的度为2,B的度为3。
树的度:一棵树中,所有节点的度中的最大值。 eg:树的度为3.
叶子节点/终端节点:节点的度为0的节点。eg:叶子节点:E,D,G,F
双亲节点/父节点:若有一个节点含有子节点,则称这个节点为该子节点的双亲节点/父节点。
孩子节点/子节点:一个节点含有的子树的根节点称为该节点的子节点。
根节点:一颗树中,没有双亲节点的节点。
节点的层次:从根节点开始,根为第一层,根的子节点为第二层,以此类推。
树的高度/深度:树中节点的最大层次。eg:树的深度/高度为3.
2.二叉树
(1)定义:
该树中每个节点的度都小于等于2;且子树有左右子树之分。下图都是二叉树。

(2)两种特殊的二叉树:
a.完全二叉树:如果一颗树的节点个数为n,深度为K,且树中每一个节点都是深度为K的满二叉树中编号从0~(n-1)的节点,则称为完全二叉树。
b.满二叉树:每层节点数都是最大值 => 如果一颗树的高度为n,且树节点的总数为,则称为满二叉树。

(3)二叉树的性质:
a.若根节点的层数为1,则一颗非空二叉树的第i层上的节点最多有个。
b.若规定只有根节点的二叉树的深度为1,则深度为K的二叉树节点总数最多为。
c.对任何一颗二叉树,如果叶子节点的个数为,节点的度为2的节点个数为
,则
+1=
。
d.具有n个节点的完全二叉树,则该树的深度为向上取整。
e.对于具有n个节点的完全二叉树,如果按照从上到下,从左到右的顺序对所有节点,从0开始编号,对于第i个节点有:
如果i>0,则双亲节点/父节点:;如果i=0,则没有双亲节点/父节点;
如果2i+1<n,则该节点有左孩子;否则没有左孩子。
如果2i+2<n,则该节点有右孩子;否则没有右孩子。
f.对于一颗完全二叉树来说,如果该树节点总数为偶数个,则节点的度为1的节点只有一个;若为奇数个,则没有节点的度为1的节点。
(4)二叉树的遍历及其代码实现:
在实现二叉树的遍历之前,首先需要创建一个类TreeNode(二叉树的节点,包含该节点的值,该节点的左孩子节点,该节点的右孩子节点),所以:
class TreeNode {public TreeNode left;//左孩子public TreeNode right;//右孩子public int val;public TreeNode(int val) {this.val = val;}
}
a.前序遍历:根节点 -> 左子树 -> 右子树
分析:

代码实现:
public void preorderTraversal(TreeNode root) {if(root == null) {return;}System.out.print(root.val + " ");preorderTraversal(root.left);preorderTraversal(root.right);
}
b.中序遍历:左子树 -> 根节点 -> 右子树
分析:

代码实现:
public void inorderTraversal(TreeNode root) {if(root == null) {return;}preorderTraversal(root.left);System.out.print(root.val + " ");preorderTraversal(root.right);
}
c.后序遍历:左子树 -> 右子树 -> 根节点
分析:
代码实现:
public void lastorderTraversal(TreeNode root) {if(root == null) {return;}preorderTraversal(root.left);preorderTraversal(root.right);System.out.print(root.val + " ");
}
(5)二叉树相关OJ题:
二叉树所有的题都会涉及到递归。所有OJ题的前提都是已经创建好了一颗树,并且知道根节点为root。
a.求树的高度。
题析:

题解:
public int getHeight(TreeNode root) {if(root == null) {return 0;}int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);return Math.max(leftHeight,rightHeight) + 1;//这里也可以用条件运算符
}
b.求树中叶子节点的个数。
题析:

题解:
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);
}
c.第i层有多少个节点。
题析:

题解:
public 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);
}
d.判断某个val值是否存在于树中。
题析:

题解:
public TreeNode getVal(TreeNode root, int val) {if(root == null) {return null;}if(root.val == val) {return root;}TreeNode leftTree = getVal(root.left,val);if(leftTree != null) {return leftTree;}TreeNode rightTree = getVal(root.right,val);if(rightTree != null) {return rightTree;}return null;
}
e.节点的总个数。
题析:

题解:
public int size(TreeNode root) {if(root == null) {return 0;}return size(root.left) + size(root.right) + 1;
}
f.检查两棵树是否相同
题析:

题解:
class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {if(p == null && q == null) {return true;}if(p == null && q != null || q == null && p != null) {return false;}if(p.val != q.val) {return false;}return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);}
}
g.另一棵树的子树
题析:

题解:
class Solution {//判断两棵树的结构是否相同private boolean isSameTree(TreeNode p, TreeNode q) {if(p == null && q == null) {return true;}if(p == null && q != null || q == 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) {return false;}if(isSameTree(root,subRoot)) {return true; }return isSubtree(root.left,subRoot) || isSubtree(root.right,subRoot);}
}
h.翻转二叉树
题析:

题解:
法一:该种方法没有利用返回值(先序遍历)。
class Solution {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;}
}
法二:利用返回值(后序遍历)。
class Solution {public TreeNode invertTree(TreeNode root) {if(root == null) {return null;}if(root.left == null && root.right == null) {return root;}TreeNode leftNode = invertTree(root.left);TreeNode rightNode = invertTree(root.right);root.left = rightNode;root.right = leftNode;return root;}
}
i.是否为平衡二叉树
题析:

题解:
法一:该方法的时间复杂度为
class Solution {public boolean isBalanced(TreeNode root) {if(root == null) {return true;}int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);if(Math.abs(leftHeight - rightHeight) > 1) {return false;} return isBalanced(root.left) && isBalanced(root.right);}private int getHeight(TreeNode root) {if(root == null) {return 0;}int leftHigh = getHeight(root.left);int rightHigh = getHeight(root.right);return Math.max(leftHigh,rightHigh) + 1;}
}
法二:可以实现时间复杂度为,只需要去修改getHeight方法,在求高度的过程中去判断是否每一个节点的高度差 <= 1。
题解:
class Solution {public boolean isBalanced(TreeNode root) {if(root == null) {return true;}return getHeight(root) >= 0;}private int getHeight(TreeNode root) {if(root == null) {return 0;}int leftHigh = getHeight(root.left);if(leftHigh == -1) {return -1;}int rightHigh = getHeight(root.right);if(rightHigh >= 0 && Math.abs(leftHigh - rightHigh) <= 1) {return Math.max(leftHigh,rightHigh) + 1;}return -1;}
}
j.二叉树的构建与遍历
题析:

题解:
import java.util.Scanner;
class TreeNode {public char val;public TreeNode left;public TreeNode right;public TreeNode(char val) {this.val = val;}
}public class Main {private static int i;//注意static修饰的变量,每次调用这个方法的时候都是对同一个变量进行修改的。//所以第二次调用该方法的时候,i不为0.所以需要在while循环中将i置0/使用非静态方法private static TreeNode createTree(String str) {TreeNode root = null;if (str.charAt(i) != '#') {root = new TreeNode(str.charAt(i));i++;root.left = createTree(str);root.right = createTree(str);}else {i++;}return root;
}//中序遍历private static void inOrder(TreeNode root) {if(root == null) {return;}inOrder(root.left);System.out.print(root.val + " ");inOrder(root.right);}public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseString str = in.nextLine();i = 0;TreeNode root = createTree(str);inOrder(root);}}
}
k.对称二叉树
题析:

题解:
class Solution {private boolean isSymmetricChild(TreeNode leftNode, TreeNode rightNode) {if(leftNode == null && rightNode != null || rightNode == null && leftNode != null){return false;}if(leftNode == null && rightNode == null) {return true;}if(leftNode.val != rightNode.val) {return false;}return isSymmetricChild(leftNode.left,rightNode.right) && isSymmetricChild(leftNode.right,rightNode.left);}public boolean isSymmetric(TreeNode root) {return isSymmetricChild(root.left, root.right);}
}
相关文章:
树与二叉树
前言: 树这个结构想必在日常生活中很常见到,而现在要介绍的是一种独特的数据结构--二叉树。 1.树 (1)定义: 是一种非线性结构,有一个特殊的节点叫做根节点,树没有前驱节点;树是递…...
SpringBoot+Vue实现简单的文件上传(Excel篇)
SpringBootVue实现简单的文件上传 1 环境 SpringBoot 3.2.1,Vue 2,ElementUI 2 页面 3 效果:只能上传xls文件且大小限制为2M,选择文件后自动上传。 4 前端代码 <template><div class"container"><el…...
科研绘图系列:R语言金字塔图(pyramid plot)
介绍 金字塔图(Pyramid chart)是一种用于展示人口统计数据的图表,特别是用于展示不同年龄段的人口数量。这种图表通常用于展示人口结构,比如性别和年龄的分布。 特点: 年龄分层:金字塔图按年龄分层,每一层代表一个年龄组。性别区分:通常,男性和女性的数据会被分别展…...
Tomcat多实例
一、Tomcat多实例 Tomcat多实例是指在同一台服务器上运行多个独立的tomcat实例,每个tomcat实例都具有独立的配置文件、日志文件、应用程序和端口,通过配置不同的端口和文件目录,可以实现同时运行多个独立的Tomcat服务器,每个服务…...
前端Vue组件化实践:自定义加载组件的探索与应用
在前端开发领域,随着业务逻辑复杂度的提升和系统规模的不断扩大,传统的开发方式逐渐暴露出效率低下、维护困难等问题。为了解决这些挑战,组件化开发作为一种高效、灵活的开发模式,受到了越来越多开发者的青睐。本文将结合实践&…...
半小时获得一张ESG入门证书【详细中英文笔记一】
前些日子,有朋友转发了一则小红书的笔记给我, 标题是《半小时获CFI官方高颜值免费证书 ESG认证》。这对考证狂魔的我来说,必然不能错过啊,有免费的羊毛不薅白不薅。 ESG课程的 CFI 官方网址戳这里:CFI 于是信心满满的…...
类形断言和和类型推导的区别是什么?
类型断言(Type Assertion)和类型推导(Type Inference)在TypeScript中的区别 如下: 定义: 类型断言:是程序员明确指定一个值的类型,即允许变量从一种类型更改为另一种类型。它不会进行…...
Spring-Spring、IoC、DI、注解开发
1、Spring是什么 Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。 Spring整体架构 Spring优点: Spring属于低侵入设计。IOC将对象之间的依赖关系交给Spring,降低组件之间的耦合,实现各个层之间的解耦,让我们更专注于业务…...
Facebook的未来蓝图:从元宇宙到虚拟现实的跨越
随着科技的不断演进和社会的数字化转型,虚拟现实(VR)和增强现实(AR)作为下一代计算平台正逐渐走进人们的视野。作为全球领先的科技公司之一,Facebook正在积极探索并推动这一领域的发展,以实现其…...
Redis6.2.1版本集群新加副本
测试数据 通过redis-benchmark生成测试数据 ./bin/redis-benchmark -h 172.31.4.18 -p 6381 -a Redis_6.2.1_Sc --cluster -t set -d 128 -n 10000000 -r 100000000 -c 200新加节点 172.31.4.18:6381> AUTH Redis_6.2.1_Sc OK172.31.4.18:6381> cluster meet 172.31.4…...
2.The DispatcherServlet
The DispatcherServlet Spring的Web MVC框架与许多其他Web MVC框架一样,是请求驱动的,围绕一个中央Servlet(即DispatcherServlet)设计,该Servlet将请求分派给控制器,并提供其他功能以促进Web应用程序的开发…...
bug定位策略
前提--用户环境层面 hosts异常:hosts文件主要是加快某个域名或者网站的解析速度,从而达到快速访问的作用,也可以屏蔽网站。hosts异常可能会导致部分网页无法访问,能够加载,但是网页无法正常显示;测试环境脏…...
基于R语言的水文、水环境模型优化技术及快速率定方法与多模型案例
在水利、环境、生态、机械以及航天等领域中,数学模型已经成为一种常用的技术手段。同时,为了提高模型的性能,减小模型误用带来的风险;模型的优化技术也被广泛用于模型的使用过程。模型参数的快速优化技术不但涉及到优化本身而且涉…...
内存函数(C语言)
内存函数 以下函数的头文件:string.h 针对内存块进行处理的函数 memcpy 函数原型: void* memcpy(void* destination, const void* source, size_t num);目标空间地址 源空间地址num,被拷贝的字节个数 返回目标空间的起始地…...
力扣 哈希表刷题回顾
哈希表理论总结 什么时候用哈希表,快速判断一个元素是否出现在集合中时,用哈希这种空间换时间的方法。 哈希函数与哈希碰撞 哈希函数是指将key映射到对应的哈希表上 哈希碰撞是指映射的过程中容易出现多对一的情况,用什么方法解决拉链法和…...
Qt 统计图编程
学习目标:Qt 折线图,柱形图和扇形统计图编程 学习基础 Qt QChart 曲线图表操作-CSDN博客 学习内容 Qt中绘制三种常见的图表非常方便, 主要步骤如下: 1. 折线图: - 使用QLineSeries定义折线数据,添加多个坐标点 - 使用QValueAxis创建X轴和Y轴 - 将…...
SQL中的谓词与谓词下推
在 SQL 查询中,谓词(Predicate)是用来对数据进行过滤的条件。它们决定了数据从数据库表中被选择的条件。理解和正确使用 SQL 谓词对于编写高效查询至关重要。 目录 什么是谓词?一个真实的故事SQL 谓词的代码示例比较谓词逻辑谓词…...
浅聊授权-spring security和oauth2
文章目录 前言自定义授权spring security授权oauth2授权概述 前言 通常说到授权,就会想到登录授权、token令牌、JWT等概念,授权。顾名思义就是服务器授予了客户端访问资源的权益,那么要实现授权有几种方案呢,三种授权方式在公司项…...
时间复杂度计算
目录 时间复杂性 ⼤O的渐进表⽰法 时间复杂性 定义:在计算机科学中,算法的时间复杂度是⼀个函数式T(N),它定量描述了该算法的运⾏时间。 时间复杂度是衡量程序的时间效率,那么为什么不去计算程序的运⾏时间呢? 1.…...
React 18 + Babel 7 + Webpack 5 开发环境搭建
文章目录 一、基础开发环境搭建1. 新建项目目录2. 项目目录结构及内容3. 安装 React 18 Babel 7 Webpack 54. 配置 Babel 和 Webpack5. 调试/构建项目 二、扩展项目支持的能力(待补充)1. JS 扩展(待补充)2. CSS 扩展(…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...
41道Django高频题整理(附答案背诵版)
解释一下 Django 和 Tornado 的关系? Django和Tornado都是Python的web框架,但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架,鼓励快速开发和干净、实用的设计。它遵循MVC设计,并强调代码复用。Django有…...
Redis上篇--知识点总结
Redis上篇–解析 本文大部分知识整理自网上,在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库,Redis 的键值对中的 key 就是字符串对象,而 val…...
工厂方法模式和抽象工厂方法模式的battle
1.案例直接上手 在这个案例里面,我们会实现这个普通的工厂方法,并且对比这个普通工厂方法和我们直接创建对象的差别在哪里,为什么需要一个工厂: 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类: 两个发…...
