二叉树(数据结构)

news2024/11/15 5:29:39

1.两种特殊的二叉树

1. 满二叉树 : 一棵二叉树,如果 每层的结点数都达到最大值,则这棵二叉树就是满二叉树 。也就是说, 如果一棵 二叉树的层数为 K ,且结点总数是2^k-1 ,则它就是满二叉树
2. 完全二叉树 : 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为 K 的,有 n个结点的二叉树,当且仅当其每一个结点都与深度为K 的满二叉树中编号从 0 n-1 的结点一一对应时称之为完 全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

2二叉树的性质

1. 若规定 根结点的层数为 1 ,则一棵 非空二叉树的第 i层上最多有(2^i-1)(i>0) 个结点
2. 若规定只有 根结点的二叉树的深度为 1 ,则 深度为 K的二叉树的最大结点数是(2^k-1)(k>=0)
3. 对任何一棵二叉树 , 如果其 叶结点个数为 n0, 度为 2 的非叶结点个数为 n2, 则有 n0 n2 1
4. 具有 n 个结点的完全二叉树的深度 k 为log(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.二叉树的存储

二叉树的存储结构 分为: 顺序存储 类似于链表的链式存储
常见是 类似于链表的链式存储。
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式 ,具体如下:
// 孩子表示法
class Node {
int val ; // 数据域
Node left ; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right ; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}
// 孩子双亲表示法
class Node {
int val ; // 数据域
Node left ; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right ; // 右孩子的引用,常常代表右孩子为根的整棵右子树
Node parent ; // 当前节点的根节点
}

4.创建二叉树

输入一串合法的前序遍历字符串,先创建根节点,不为'#'再递归创建左孩子,如果是就回退到上一个节点,再递归创建左孩子右孩子,连续遇到两个‘#’则一个子树创建完成。

代码如下:

class Main {
    public static class TreeNode {
        Character val;
        TreeNode left;
        TreeNode right;
        TreeNode() {}
        TreeNode(Character val) {
            this.val = val;
        }
        TreeNode(Character val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }//内部类(树节点)
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
      //  while (in.hasNextInt()) { // 注意 while 处理多个 case
            String s = in.nextLine();
            TreeNode root = createTree(s);//递归创建二叉树
            order(root);
     //   }
    }


    public static int i = 0;
    public static TreeNode createTree(String s) {
        TreeNode root = null;
        if (s.charAt(i) != '#') {
            root = new TreeNode(s.charAt(i));
            i++;
            root.left = createTree(s);
            root.right = createTree(s);
        } else {
            i++;
        }
        return root;
    }
}
例:
root = [1,null,2,3]  

5.二叉树的基本操作

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


// 获取叶子节点的个数
public static int leafSize = 0;
int getLeafNodeCount(Node root){
     if(root==null){
            return ;
        }
        if(root.left==null&&root.right==null){
            leafSize++;
        }
        getLeafNodeCount1(root.right);
        getLeafNodeCount1(root.left);
    }



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


// 获取二叉树的高度
int getHeight(Node root){
    if(root==null){
        return 0;
    }
    int leftL=getHeight(root.left);
    int rightL=getHeight(root.right);
   // return right>left?right+1:left+1;
    return Math.max(rightL,leftL)+1;
}

// 检测值为value的元素是否存在
Node find(Node root, int val){
    if(root==null){
        return null;
    }
    if(root.val==val){
        return root;
    }
    TreeNode leftT=find(root.left,val);
    if(leftT!=null) {
        return leftT;
    }
    TreeNode rightT=find(root.right,val);
    if(rightT!=null){
        return rightT;
    }
    return null;
}


//层序遍历
void levelOrder(Node root){
    if(root==null){
        return ;
    }
    Queue<TreeNode> queue=new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()){
        TreeNode cur= queue.poll();
        System.out.println(cur.val+" ");
        if(cur.left!=null){
            queue.offer(cur.left);
        }
        if(cur.right!=null){
            queue.offer(cur.right);
        }
    }
    System.out.println();
}


// 判断一棵树是不是完全二叉树
boolean isCompleteTree(Node root){
    if(root==null){
        return true;
    }
    int leftL=getHeight(root.left);
    int rightL=getHeight(root.right);
    if(leftL-rightL>1||rightL-leftL>1){
        return false;
    }
    return isBalanced(root.left)&&isBalanced(root.right);//时间复杂度O(n^2)
    //return getHeight2>0  时间复杂度O(n)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2089901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为你的LLM应用增加记忆能力

1. 记忆系统的重要性 我们都知道&#xff0c;大模型本身是无状态、无记忆的。默认情况下&#xff0c;我们向大模型发起的每次提问&#xff0c;在其内部都会被视为一次全新的调用。尽管诸如 ChatGPT 等聊天应用内置了部分记忆功能&#xff0c;可以记录用户最近几轮的聊天信息&a…

ChatTTS容器构建教程

一、模型介绍 ChatTTS 是专门为对话场景设计的文本转语音模型&#xff0c;例如 LLM 助手对话任务。它支持英文和中文两种语言。最大的模型使用了 10 万小时以上的中英文数据进行训练。在 HuggingFace 中开源的版本为 4 万小时训练且未 SFT 的版本。 ChatTTS WebUI如下&#x…

【单片机原理及应用】实验:LED循环控制

目录 一、实验目的 二、实验内容 三、实验步骤 四、记录与处理 五、思考 六、成果文件提取链接 一、实验目的 熟悉Proteus x8原理图与C51程序的联合仿真调试方法&#xff0c;掌握C51延时函数和循环控制的方法 二、实验内容 【参照图表】 &#xff08;1&#xff09;创建一…

晚宴扫码查询桌号

在现代社交活动中&#xff0c;晚宴的组织和管理越来越依赖于技术手段。为了提高晚宴的效率和参与者的体验&#xff0c;我们可以通过一个简单的扫码查询系统来实现快速查找桌号和座位号。以下是详细步骤&#xff1a; 1. 电脑端上传查询信息 访问云分组官网。 使用微信扫码登录…

AcrelEMS3.0企业微电网智慧能源平台的设计与应用-安科瑞 蒋静

1系统概述 1.1 概述 2020年9月&#xff0c;我国明确提出2030年“碳达峰”与2060年“碳中和”目标。2022年6月&#xff0c;科技部、国家发展改革委、工业和信息化部、生态环境部、住房城乡建设部、交通运输部、中科院、工程院、国家能源局共同研究制定了《科技支撑碳达峰碳中和…

netty编程之实现断点续传(分片发送)功能

写在前面 在我们使用各种网盘的时候&#xff0c;可以随时的暂停上传&#xff0c;然后继续上传&#xff0c;这其实就是断点续传的功能&#xff0c;本文就看下在netty中如何实现断点续传的功能。 1&#xff1a;核心点介绍 1.1&#xff1a;RandomAccessFile RandomAccessFile类…

汽车信息安全--MCU Flash读保护真的没有后门吗?

目录 1.修bug修出的灵感 2.串行编程接口协议 3.毛刺攻击 4.RH850 串行编程模式 5.小结 1.修bug修出的灵感 ECU量产后通过密码控制来防止通过Debug口读取Flash的程序和数据。 这是应该是共识了&#xff0c;但是这样做真的就万无一失了吗&#xff1f; 最近解决了个问题&…

Linux操作系统在虚拟机VM上的安装【CentOS版本】

目录 准备工作 "CPU虚拟化"的方法 VMware的安装 Linux镜像文件的下载 开始安装 声明 新建虚拟机 安装CentOS7.6 配置Linux(CentOS7.6)操作系统 配置分区【学习者可以直接点击自动配置分区&#xff0c;不过还是建议学习一下手动分区】 分区原则 添加分区 …

适配制造业的设备管理系统有哪些?本文给你答案!

本文将带大家盘点10款设备管理系统&#xff0c;供企业选型参考。 外包单位数量众多&#xff0c;但难以对他们进行统一协同管理&#xff1f;危险作业的作业申请、作业审批使用线下纸质版&#xff0c;不仅效率低还管控力不足&#xff1f;相关部门想监测、管理设备安全风险&#x…

AcWing898. 数字三角形

线性DP 董晓老师的讲解是从下标0开始算的&#xff0c;其实我们从1开始也可以&#xff0c;我感觉这里从1开始更好理解。是从下往上计算的。j负责列的计算&#xff0c;往上计算时逐步收窄横向的范围&#xff0c;i是纵向的从下往上算&#xff0c; 下面是内存布局 下面是逻辑上的…

【网络安全】打开这份“开学礼” 谨防骗子“冲业绩”

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s…

今年读过最绝的一本书!《自然语言处理原理、方法与应用》,几乎把自然语言处理讲透了【附PDF】

书籍内容介绍&#xff1a; 本书系统阐述自然语言处理基础知识&#xff0c;以及自然语言处理高级模型应用等高级知识。 全书共11章&#xff1a;第1&#xff5e;5章为自然语言处理的基础知识&#xff0c;第6&#xff5e;11章将自然语言处理知识应用于实战。书中主要内容包括预训…

99% 的人都不知道,哪种 Python 循环最快?

大家好&#xff0c;在Python编程中&#xff0c;循环是我们经常使用的工具&#xff0c;用来重复执行一些代码块。我们通常会在 for 循环、while 循环和列表推导式中选择一种来解决问题。但你是否曾想过&#xff1a;哪种循环效率最高&#xff1f; 今天&#xff0c;我们就来一次轻…

Vue -- 总结 02

Vue脚手架 安装Vue脚手架&#xff1a; 在cmd中安装(输入):npm install -g vue/cli 如果下载慢或下载不了&#xff0c;可以安装(cmd输入)淘宝镜像:npm config set registry https://registry.npmmirror.com 用命令创建Vue项目 在要创建的vue项目的文件夹里输入 cmd 回车 创…

CSS 2D3D转换与动画

CSS 2D&3D转换与动画 字体图标 字体图标展示的是图标&#xff0c;本质是字体 处理简单的&#xff0c;颜色单一的图片&#xff0c;使用字体图标 使用&#xff1a; 下载&#xff1a;https://www.iconfont.cn/ 引入字体图标样式表 对应标签上classz增加对应的类名&…

使用pytest的 reporting特性来生成报告

特性 1.HTML 报告&#xff1a;使用 pytest-html 插件&#xff0c;你可以生成 HTML 格式的测试报告。只需在项目的 pytest.ini 文件中添加以下内容&#xff1a; [pytest] addopts --htmlreport.html然后&#xff0c;在运行 pytest 时&#xff0c;将会生成一个名为 report.htm…

Serilog文档翻译系列(二) - 设置AspNetCore应用程序

Serilog 日志记录适用于 ASP.NET Core。此包将 ASP.NET Core 的日志消息通过 Serilog 进行路由&#xff0c;使你可以将有关 ASP.NET 内部操作的信息写入与应用程序事件相同的 Serilog 接收器中。 安装并配置了 Serilog.AspNetCore 后&#xff0c;你可以直接通过 Serilog 或ASP…

CDS Association

CDS view Association 引入的缘由 CDS 视图不会被业务用户直接访问&#xff0c;而是会被 ABAP 程序、Fiori 应用程序或 BI 前端工具使用。假设在 5 个不同的表上使用 JOINS 创建了 CDS 视图&#xff0c;则每次触发此 CDS 视图时都会执行此 JOIN 条件。即使业务用户只查看 2 个…

十分钟弄懂最快的APP自动化工具uiautomator2

相信很多使用appium做过APP自动化的人都深有感触&#xff1a; appium运行慢、时间长uiautomatorviewer定位元素时得关掉appium server在低版本的appium上获取toast需要切换automationName 现在有一款自动化测试工具uiautomator2&#xff0c;它几乎完美的避免了以上的问题。简…

数据结构---循环队列---树的基本概念

目录 一、队列 1.1.队列 1.创建循环队列&#xff08;顺序结构&#xff09; 2.判断队满 3.判断队空 4.进队 5.出队 6.销毁 二、树 2.1.树的特点 2.2.基本概念 1.根节点 2.分支节点 3.叶节点 4.层 5.深度 6.高度 7.度 2.3.二叉树 1.特点 2.遍历方式 2.4.满二…