数据结构_二叉树

news2025/2/25 5:15:39

目录

一、树型结构

二、二叉树

2.1 概念

2.2 特殊的二叉树

 2.3 二叉树的性质

2.4 二叉树的存储

2.5 遍历二叉树

2.6 操作二叉树

总结


一、树型结构

是一种非线性的数据结构,它是由 n(n>=0) 个有限结点组成一个具有层次关系的集合,一棵 n 个结点的树有 n-1 条边

  • 结点的度:一个节点具有的子树个数称为该结点的度。如上图,结点 A 的度为 6。
  • 树的度:一棵树中,所有结点度的最大值称为树的度。如上图,树的度为 6。
  • 叶子结点 (终端结点):度为 0 的结点称为叶子结点。如上图,B、C、H、I、N 等结点为叶子结点。
  • 父结点 (双亲结点):若一个结点含有子结点,则称该结点为其子结点的父节点。如上图,A 是 B 的父结点。
  • 根结点:是每棵树的起始结点,即没有父结点的结点。如上图,A 为根结点。
  • 子结点 (孩子结点):一个结点含有的子树的根结点,称为该结点的子节点。如上图,B 是 A 的子结点。
  • 结点的层次:从根结点开始,根结点为第 1 层,根结点的子结点为第 2 层,以此类推。如上图,结点 A 为第 1 层,结点 B、C、D 等为第 2 层。
  • 树的高度 (深度):树中结点的最大层次。如上图,树的高度为 4。
  • 分支结点:度不为 0 的结点。
  • 兄弟结点:具有相同父结点的结点互为兄弟。
  • 堂兄弟结点:父结点在同一层的结点互为堂兄弟。
  • 结点的祖先:从根结点到该结点分支上的所有结点。如上图,A 是所有结点的祖先。
  • 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图,所有结点都是 A 的子孙。
  • 森林:由 m(m>=0) 棵互不相交的树组成的集合称为森林。

二、二叉树

2.1 概念

一棵二叉树是结点的一个有限集合,二叉树有两种情况:

① 空树

由一个根结点加上两棵分别称为左子树右子树的二叉树组成。

【特点】

1、二叉树不存在度大于 2 的结点;

2、二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树。


2.2 特殊的二叉树

1、满二叉树:若一棵二叉树每层的结点数都达到最大值,则这棵树就是满二叉树。即若一棵二叉树的高度为 k,且结点总数是 2^{k}-1,则它就是满二叉树。

2、完全二叉树:满二叉树是一种特殊的完全二叉树。对于高度为 K,有 n 个结点的二叉树,当且仅当其每个结点都与高度为 k 的满二叉树中编号从 0 至 n-1 的结点一一对应时称为完全二叉树。


 2.3 二叉树的性质

  • 一棵非空二叉树的第 k 层上最多有 2^{k-1}(k>0) 个结点;
  • 高度为 k 的二叉树最大结点数为 2^{k}-1(k>=0)
  • 叶子结点个数为 n_{0}度为 2 的结点个数为 n_{2},则有 n_{0} = n_{2}+1
  • 有 n 个结点的完全二叉树高度为 [log_{2}n]+1("[]"为取整)
  • 一棵有 n 个结点的完全二叉树,对于其编号为 i 的结点有:
  • 若 i > 0,父结点编号:[(i-1) / 2];若 i = 0,则 i 为根结点编号,无父结点。
  • 若 2i+1 <= n,左孩子编号:2i+1;反之无左孩子。
  • 若 2i+2 <= n,右孩子编号:2i+1;反之无右孩子。

2.4 二叉树的存储

二叉树的存储结构分为:顺序存储和链式存储

二叉树的链式存储是通过一个一个结点引用构造出的,例如,孩子表示法和孩子双亲表示法:

    //孩子表示法
    class Node {
        int val; //数据域
        Node left; //左孩子
        Node right; //右孩子
    }

    //孩子双亲表示法
    class Node {
        int val; //数据域
        Node left; //左孩子
        Node right; //右孩子
        Node parent; //当前节点的父亲节点
    }

2.5 遍历二叉树

【前中后序遍历】

前序(NLR):根结点 → 左子树 → 右子树;(根左右)

中序(LNR):左子树 → 根结点 → 右子树;(左根右)

后序(LRN):左子树 → 右子树 → 根结点;(左右根)

前序:ABDEGCF

中序:DBGEAFC

后序:DGEBFCA

public class BinaryTree {

    //孩子表示法
    static class TreeNode {
        public String val; //数据域
        public TreeNode left; //左孩子
        public TreeNode right; //右孩子

        public TreeNode(String val) {
            this.val = val;
        }
    }

    //构建树,返回根结点
    public TreeNode createTree() {
        TreeNode A = new TreeNode("A");
        TreeNode B = new TreeNode("B");
        TreeNode C = new TreeNode("C");
        TreeNode D = new TreeNode("D");
        TreeNode E = new TreeNode("E");
        TreeNode F = new TreeNode("F");
        TreeNode G = new TreeNode("G");

        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        E.left = G;
        C.left = F;

        return A;
    }

    //前序遍历
    public void preOrder(TreeNode root) {
        //若为空树,返回
        if (root == null) {
            return;
        }
        System.out.print(root.val + " "); //根
        preOrder(root.left); //左
        preOrder(root.right); //右
    }

    //中序遍历
    public void inOrder(TreeNode root) {
        //若为空树,返回
        if (root == null) {
            return;
        }
        inOrder(root.left);//左
        System.out.print(root.val + " ");//根
        inOrder(root.right);//右
    }

    //后序遍历
    public void postOrder(TreeNode root) {
        //若为空树,返回
        if (root == null) {
            return;
        }
        postOrder(root.left);//左
        postOrder(root.right);//右
        System.out.print(root.val + " ");//根
    }
}

public class Main {
    public static void main(String[] args) {
        //创建二叉树对象
        BinaryTree binaryTree = new BinaryTree();
        //构建二叉树
        BinaryTree.TreeNode root = binaryTree.createTree();

        binaryTree.preOrder(root);//前序:A B D E G C F 
        System.out.println();
        binaryTree.inOrder(root);//中序:D B G E A F C
        System.out.println();
        binaryTree.postOrder(root);//后序:D G E B F C A 
    }
}

【层序遍历】 

层序遍历:即自上而下、从左至右逐层访问树的结点的遍历过程。


2.6 操作二叉树

采用子问题思路来实现二叉树的操作。

1、获取树中结点个数

    //获取树中结点的个数
    public int size(TreeNode root) {
        //若为空树,返回
        if (root == null) {
            return 0;
        }
        //返回根结点的左子树 + 根结点的右子树 + 根结点本身
        return size(root.left) + size(root.right) + 1;
    }

2、获取树中叶子结点个数

    //获取叶子结点的个数
    public int getLeafNodeCount(TreeNode root) {
        //若为空树,返回
        if (root == null) {
            return 0;
        }
        //若无左子树与右子树,便是叶子结点
        if (root.left == null && root.right == null) {
            //是叶子结点,返回 1
            return 1;
        }
        //返回根结点的左子树、右子树中的叶子结点
        return getLeafNodeCount(root.left) + getLeafNodeCount(root.right);
    }

 3、获取第 K 层结点个数

    //获取第 K 层结点的个数
    public int getKLevelNodeCount(TreeNode root, int k) {
        //若为空树,返回
        if (root == null) {
            return 0;
        }
        //第 K 层是第 1 层根结点的第 K-1 层,
        //也是第 2 层结点的第 K-2 层。
        //即第 K 层结点的第 1 层,
        if (k == 1) {
            return 1;
        }
        //返回根结点的左子树、右子树的第 K 层结点
        return getKLevelNodeCount(root.left, k-1) + getKLevelNodeCount(root.right, k-1);
    }

 4、获取二叉树的高度

    //获取二叉树的高度
    public int getHeight(TreeNode root) {
        //若为空树,返回
        if (root == null) {
            return 0;
        }
        //左子树高度
        int leftHeight = getHeight(root.left);
        //右子树高度
        int rightHeight = getHeight(root.right);

        //根结点的左子树与右子树对比,
        //谁高返回谁 + 根结点本身,即左(右)子树高度 + 1。
        return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1;
    }

5、检测值为 val 的元素是否存在

    //检测值为 val 的元素是否存在
    public TreeNode find(TreeNode root, String val) {
        //若为空树,返回
        if (root == null) {
            return null;
        }
        //判断根结点元素
        if (root.val == val) {
            return root;
        }
        //判断根结点的左子树
        TreeNode left = find(root.left, val);
        if (left != null) {
            return left;
        }
        //判断根结点的右子树
        TreeNode right = find(root.right, val);
        if (right != null) {
            return right;
        }

        return null;
    }

总结

1、一棵 n 个结点的树有 n-1 条边。

2、二叉树不存在度大于 2 的结点。

3、二叉树的存储结构分为:顺序存储和链式存储。

4、前序(根左右);中序(左根右);后序(左右根)。

5、层序遍历:自上而下、从左至右逐层访问树的结点的遍历过程。

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

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

相关文章

CatBoost算法详解

CatBoost算法详解 CatBoost&#xff08;Categorical Boosting&#xff09;是由Yandex开发的一种基于梯度提升决策树&#xff08;GBDT&#xff09;的机器学习算法&#xff0c;特别擅长处理包含类别特征的数据集。它不仅在精度和速度上表现出色&#xff0c;还对类别特征有天然的…

工业园安全生产新保障:广东地区加强可燃气体报警器校准检测

广东&#xff0c;作为我国经济的重要引擎&#xff0c;拥有众多工业园区。 这些工业园区中&#xff0c;涉及化工、制药、机械制造等多个领域&#xff0c;每天都会产生和使用大量的可燃气体。因此&#xff0c;可燃气体报警器的安装与校准检测&#xff0c;对于保障工业园区的安全…

太湖远大毛利率下滑:研发费用率远低同行,募投项目合理性疑点重重

《港湾商业观察》黄懿 6月20日&#xff0c;浙江太湖远大新材料股份有限公司&#xff08;以下简称“太湖远大”&#xff0c;873743.NQ&#xff09;即将迎来过会。 2023年11月30日&#xff0c;太湖远大所提交的上市申请材料正式获北交所受理&#xff0c;保荐机构为招商证券&…

渗透测试基础(五) 获取WiFi密码

1. 前提条件 需要无线网卡&#xff0c;kali无法识别电脑自带的网卡。 2. 实验步骤&#xff1a; 2.1 查看网卡 命令&#xff1a;airmon-ng 2.2 启动网卡监听模式 命令airmon-ng start wlan0 检查下是否处于监听模型&#xff1a;ifconfig查看一下&#xff0c;如果网卡名加…

技术支持与开发助手:Kompas AI的革新力量

一、引言 随着技术发展的迅猛进步&#xff0c;技术开发的高效需求日益增加。开发人员面临着更复杂的项目、更紧迫的时间表以及不断提高的质量标准。在这种背景下&#xff0c;能够提供智能支持的工具变得尤为重要。Kompas AI 正是在这种需求下应运而生的。它通过人工智能技术&a…

word复制技巧二则

1 纵向复制 按下Alt键&#xff0c;按下鼠标左键拖动&#xff0c;选中要纵向复制的内容&#xff0c;如下图&#xff0c; 再粘贴即可&#xff1b; 2 整页复制 在页的任意位置单击&#xff0c;然后按CtrlA&#xff0c;这会选中整页&#xff1b;然后再复制粘贴即可&#xff1b;

企业为什么要进行数据资产管理工作:价值与案例剖析

在数字化浪潮席卷全球的今天&#xff0c;数据已经成为企业不可或缺的重要资产。数据资产管理&#xff0c;作为确保数据资产价值得以最大化利用的关键环节&#xff0c;正逐渐成为企业战略规划中的核心议题。本文将深入剖析企业进行数据资产管理工作的必要性&#xff0c;并结合实…

TikTok达人带货合作秘籍:从联系到合作,一站式合作流程解析

在数字化营销时代&#xff0c;TikTok作为一个全球性的短视频平台&#xff0c;已成为品牌推广的重要渠道。与TikTok达人建立合作关系&#xff0c;借助他们的影响力和粉丝基础&#xff0c;可以实现快速有效的带货效果。本文Nox聚星将和大家详细讨论如何有效地与选定的TikTok达人建…

【机器学习】【深度学习】MXnet神经网络图像风格迁移学习简介

使用部分 一、编程环境 编程环境使用Windows11上的Anaconda环境&#xff0c;Python版本为3.6. 关于Conda环境的建立和管理&#xff0c;可以参考我的博客&#xff1a;【Anaconda】【Windows编程技术】【Python】Anaconda的常用命令及实操 二、项目结构&#xff08;代码非原创…

【人机交互 复习】第8章 交互设计模型与理论

一、引文 1.模型&#xff1a; 有的人成功了&#xff0c;他把这一路的经验中可以供其他人参考的部分总结了出来&#xff0c;然后让别人套用。 2.本章模型 &#xff08;1&#xff09;计算用户完成任务的时间&#xff1a;KLM &#xff08;2&#xff09;描述交互过程中系统状态的变…

众包招聘零工兼职任务发布人力资源招聘小程序

&#x1f4e2;众包招聘零工兼职任务发布——人力资源招聘小程序全攻略 一、引言&#xff1a;打破传统&#xff0c;开启零工新时代 随着社会的快速发展&#xff0c;零工经济已成为一种不可忽视的就业模式。为了满足广大求职者与招聘者的需求&#xff0c;众包招聘零工兼职任务发…

好用的矩阵系统推荐,抖去推,筷子剪辑,超级编导哪个好用?

抖去推、筷子剪辑、超级编导都是很流行的视频内容创作形式&#xff0c;每个都有自己的特点和受众群体。要选择哪个最好&#xff0c;取决于客户您的需求&#xff0c;下面也整理了以下各个产品的收费模式及各自优势&#xff0c;可作为参考进行选择 抖去推&#xff0c;抖去推是一款…

go的context

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【MySQL】事务二

事务二 1.数据库并发的场景2.读-写2.1 3个记录隐藏字段2.2 undo日志2.3 模拟 MVCC2.4 Read View2.5 RR 与 RC的本质区别 3.读-读4.写-写 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我…

音乐人王海军新歌《我没让你骄傲你却视我如宝》上线 好评如潮

时光飞逝&#xff0c;岁月如歌&#xff0c;华语乐坛向来不缺乏岁月金曲的沉淀与洗礼。2024&#xff0c;一首名为《我没让你骄傲你却视我如宝》的歌曲突然火爆全网&#xff0c;一经发行&#xff0c;便立刻赢得了广大歌迷朋友一致好评&#xff0c;共鸣内心&#xff0c;带来温暖与…

计算机网络 —— 应用层(FTP)

计算机网络 —— 应用层&#xff08;FTP&#xff09; FTP核心特性&#xff1a;运作流程&#xff1a; FTP工作原理主动模式被动模式 我门今天来看应用层的FTP&#xff08;文件传输协议&#xff09; FTP FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#x…

Docker+MySQL:打造安全高效的远程数据库访问

在现代应用开发和部署中&#xff0c;数据库是关键组件之一。无论是开发环境还是生产环境&#xff0c;快速、可靠地部署和管理数据库都是开发人员和运维人员面临的常见挑战之一。 Docker是一种流行的容器化技术&#xff0c;它使得应用程序的部署和管理变得非常简单和高效。通过使…

工业制造领涉及的8大常见管理系统,如mes、scada、aps、wms等

在工业生产和制造领域有一些常见的管理系统&#xff0c;很多小伙伴分不清&#xff0c;这次大美B端工场带领大家了解清楚。 MES&#xff08;Manufacturing Execution System&#xff0c;制造执行系统&#xff09;&#xff1a; MES是一种用于监控、控制和优化生产过程的软件系统…

Java众包招聘零工兼职任务发布人力资源招聘小程序

&#x1f4e2;众包招聘零工兼职任务发布——人力资源招聘小程序全攻略 一、引言&#xff1a;打破传统&#xff0c;开启零工新时代 随着社会的快速发展&#xff0c;零工经济已成为一种不可忽视的就业模式。为了满足广大求职者与招聘者的需求&#xff0c;众包招聘零工兼职任务发…

Python中文自然语言处理(NLP)中文分词工具库之pkuseg使用详解

概要 在中文自然语言处理(NLP)中,分词是一个基础且关键的任务。pkuseg 是由北京大学开发的一个中文分词工具,专为处理现代汉语而设计。它采用了先进的深度学习技术,能够准确地进行中文分词,同时支持自定义词典和多领域分词。本文将详细介绍 pkuseg 库,包括其安装方法、…