数据结构(4)树形结构——二叉树(概述、前序、中序、后序、层序遍历JAVA实现)

news2025/1/10 18:52:09

目录

4.1.树

4.2.二叉树

4.2.1.概述

4.2.3.存储结构

4.2.3.遍历

1.逻辑简介

 2.代码示例


4.1.树

树,由n(n≥0)个有限节点和边组成一个具有层次关系的数据结构。树需要满足以下条件:

  • 任何结点的子节点不相交。
  • 任何子结点只有一个父节点。
  • N个结点,N-1条边。

对于一个非空树(结点数≥0),具有以下性质:

  • 起始结点称为“根”
  • 除根结点外可分为m个互不相交的有限集合,其中每个集合本身也是一棵树,称为原来这棵树的“子树”。

 树的基本术语:

  • 结点的度:节点的子树个数
  • 树的度:树的所有结点中最大的度数
  • 叶结点:度为0的结点
  • 父结点:有子树的结点都是它的子树的根结点
  • 子结点:若A是B的父结点,则B是A的子节点
  • 兄弟结点:具有同一父结点的结点彼此是

4.2.二叉树

4.2.1.概述

二叉树是一种每个结点的度不大于2的树,由根结点和左子树、右子树组成,具有以下五种姿态:

 除了五种基本姿态外,还有三种比较特殊的姿态:

4.2.3.存储结构

二叉树可以用两种结构存储,一种是链表,一种是数组。

数组表示的话第一个位置存储的根结点,挨着根结点的是根结点的左右孩子,接下来是根结点左孩子的左右孩子,右孩子的左右孩子,以此类推:

 数组仅适合完全二叉树(完美二叉树是特殊的完全二叉树),以为当表示非完全而二叉树,会出现大面积内存空间浪费的情况:

4.2.3.遍历

1.逻辑简介

二叉的遍历,本质上是二维结构的线性化,二叉树本来是非线性的,但是其结果最后是线性的。

二叉树的遍历根据访问当前子树的根结点的顺序分为四种:

  • 先序遍历
  • 中序遍历
  • 后序遍历

除此之外还有一种特殊的遍历,层序遍历,按照每一层来遍历。

层序遍历需要用到一个队列来实现:

首先是根结点入队,然后访问根结点,根结点左右孩子顺序入队,根结点出队,然后队列中的后续结点重复上述的出队入队流程,直到队列为空,整个层序遍历过程就结束。

 2.代码示例

二树的结点:

public class Node {
    //数据域
    private int data;
    //指针域
    private Node left;
    private Node right;

    //遍历标志
    private boolean isOrder;

    {
        isOrder=false;
    }

    public Node(){

    }

    public Node(int data){
        this.data=data;
    }
    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }

    public boolean isOrder() {
        return isOrder;
    }

    public void setOrder(boolean order) {
        isOrder = order;
    }
}

 各种遍历的实现:

public class BinaryTree {

    //判断BT是否为空
    public static boolean isEmpty(Node root){
        //判断操作
        return  root==null?true:false;
    }


    //先序建树
    public static Node create(Node node,Scanner scanner){
        Integer data=Integer.parseInt(scanner.next());
        if(data!=-1){
            node=new Node();
            node.setData(data);
            node.setLeft(create(node,scanner));
            node.setRight(create(node,scanner));
        }
        //以防万一,如果节点为叶节点时,将其左右指针置空
        if(data==-1){
            node.setLeft(null);
            node.setRight(null);
        }
        return node;
    }

    //递归先序遍历二叉树
    public static void pre(Node node){
        //需要给节点增加一个遍历状态标志位
        //每次递归回溯时需要判断当前节点的标志位是否为已遍历状态
        //否则会徘徊在叶节点,堆栈溢出
        if(node!=null&!node.isOrder()){
            System.out.println(node.getData());
            node.setOrder(true);
            pre(node.getLeft());
            pre(node.getRight());
        }
    }

    //中序遍历
    public static  void mid(Node node){
        if(node!=null&!node.isOrder()){
            node.setOrder(true);
            mid(node.getLeft());
            System.out.println(node.getData());
            mid(node.getRight());
        }
    }

    //后续遍历
    public static void post(Node node){
        if(node!=null&!node.isOrder()){
            node.setOrder(true);
            mid(node.getLeft());
            mid(node.getRight());
            System.out.println(node.getData());
        }
    }

    //层序遍历
    public static void level(){
        //递归法
        if (!queue.isEmpty()) {
            //取出队首元素
            Node node = queue.exit();
            //打印节点数据
            System.out.println(node.getData());
            //左孩子入队
            queue.Enter(node.getLeft());
            //右孩子入队
            queue.Enter(node.getRight());

            level();
        }

        //循环法
        /*while (!queue.isEmpty()) {
            //取出队首元素
            Node node = queue.exit();
            //打印节点数据
            System.out.println(node.getData());
            //左孩子入队
            queue.Enter(node.getLeft());
            //右孩子入队
            queue.Enter(node.getRight());
        }*/
    }
}

需要注意的是,层序遍历的话要用到一个队列来实现,这个队列的话用的就是之前在线性结构里实现的那个队列:

public class queue {
    private static Node[] que;
    //头指针
    private static int first;
    //尾指针
    private static int last;
    //初始化
    static{
        que=new Node[100];
        first=0;
        last=-1;
    }

    //入队
    public static void Enter(Node node){
        que[++last]=node;
    }
    //出队
    public static Node exit(){
        Node node=que[first++];
        return node;
    }
    //判空
    public static boolean isEmpty(){
        return (que[first]==null&&first==last) ? true:false;
    }
}

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

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

相关文章

carsim 2020 安装说明及多个版本冲突问题解决

在E盘新建一个文件夹,命名为Carsim 2020在Carsim 2020文件夹中,再新建两个文件夹,分别命名为carsim 2020.0_Data和carsim 2020.0_Prog以管理员的身份运行Setup_CarSim_2020.0_r125554.exe,并将安装目录分别选择第2步中的carsim 20…

【LeetCode每日一题:1742. 盒子中小球的最大数量~~~Map+遍历模式+计数】

题目描述 你在一家生产小球的玩具厂工作,有 n 个小球,编号从 lowLimit 开始,到 highLimit 结束(包括 lowLimit 和 highLimit ,即 n highLimit - lowLimit 1)。另有无限数量的盒子,编号从 1 到…

如何设置网络访问 SQL Express?

网络访问 SQL Express 安全和连接SQL Server 配置Windows 防火墙配置连接服务器一旦在本地计算机上设置了 SQL Express,就可以允许网络成员进行远程连接。有不同的方法可以做到这一点,这些步骤可能不适用于现有的网络环境或身份验证方法。下面是在本地计算机上设置的 SQL Ser…

语音前处理技术在会议场景中的应用及挑战

编者按: 随着在线会议的普及,用户已经不再满足于能听到,而是要有更为极致的听感体验,如何能够在复杂多变的应用场景中依旧保证声音清晰流畅是对会议系统的极大挑战。LiveVideoStackCon2022上海站大会邀请到了全时 音视频研发部经理…

网页大作业代码自取【HTML+CSS制作美味糖果网站】

🎀 精彩专栏推荐👇🏻👇🏻👇🏻 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业…

【2015】408联考数据结构真题整理

2015 1 题目 答案:A 解析 2 题目 解析 3 题目 解析 4 题目 解析 5 题目 答案:D 解析 6 题目 解析 7 题目 答案:A 解析 8 题目 答案:C 解析 9 题目 解析 10 题目 解析 11 题目 解析 41 题目 答案: 3&a…

Android 深入理解View.post()获取宽高、Window加载View原理

文章目录背景:如何在onCreate()中获取View的宽高?View.post()原理Window加载View流程setContentView()ActivityThread#handleResumeActivity()总结扩展Window、Activity及View三者之间的关系是否可以在子线程中更新UI资料背景:如何在onCreate…

从React源码分析看useEffect

热身准备 这里不再讲useLayoutEffect,它和useEffect的代码是一样的,区别主要是: 执行时机不同;useEffect是异步, useLayoutEffect是同步,会阻塞渲染; 初始化 mount mountEffect 在所有hook…

day34 文件上传黑白盒审计逻辑中间件外部引用

前言 #知识点: 1、白盒审计三要素 2、黑盒审计四要素 3、白黑测试流程思路 #详细点: 1、检测层面:前端,后端等 2、检测内容:文件头,完整性,二次渲染等 3、检测后缀:黑名单&am…

强化学习 马尔科夫决策过程(价值迭代、策略迭代、雅克比迭代、蒙特卡洛)

文章目录一、马尔科夫过程Markov Decision Process(MDP)1.简介2、Markov 特性3、Markov 奖励过程符号表示MRPs的贝尔曼方程4、Markov决策过程符号表示转化MRPs的贝尔曼方程优化问题贝尔曼最优方程二、价值迭代求解1、回顾2、算法3、案例案例1案例2三、策…

Linux学习笔记13 - 进程间通信(IPC)(四)

消息队列 消息队列(message queue)即消息的列表,亦称报文队列,也叫做信箱。是Linux的一种通信机制,这种通信机制传递的数据具有某种结构,而不是简单的字节流[1]。消息队列的本质其实是一个内核提供的链表,内核基于这个链表&#…

有限元仿真分析误差来源之边界条件设置-动载荷

作者:青梅煮酒 导读:前不久,笔者在仿真秀平台分享一篇关于有限元仿真分析误差来源之边界条件,约束和point mass,引发了工程师朋友们广泛关注和思考。通过与他们交流和讨论,我也有所所获。今天继续开展有限…

【强化学习论文合集】AAAI-2022 | 人工智能CCF-A类会议(附链接)

人工智能促进会(AAAI)成立于1979年,前身为美国人工智能协会(American Association for Artificial Intelligence),是一个非营利性的科学协会,致力于促进对思想和智能行为及其在机器中的体现的潜在机制的科学理解。AAAI旨在促进人工智能的研究…

利用HbuilderX制作简单网页: HTML5期末大作业——html5漫画风格个人主页

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置,有div的样式格局,这个实例比较全面,有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 ⚽精彩专栏推荐&#x1…

用JAVA详解冒泡排序

1.代码段实现&#xff1a;&#xff08;混的只需要把第一个拿走即可&#xff09; public static void main(String[]args){int []arr new int [] {99,68,97,86,65,94,33,72};System.out.println("排序前的数组为&#xff1a;");for (int i 0;i < arr.length;i){…

Java入门

文章目录数组一维数组多维数组Arrays工具类数组中常见异常String、StringBuilder、StringBufferString类String的特性String对象的创建String常用方法StringBuilder类StringBuffer类StringBuffer对象的创建StringBuffer类的常用方法String、StringBuffer、StringBuilder区别日期…

Go:日志滚动(rolling)记录器 lumberjack 简介

文章目录简介简单使用1. Logger 结构体2. backup日志文件的文件名3. 获取文件句柄4. 日志文件backup5. 日志滚动后处理6. 收集旧日志文件7. 后处理小结简介 lumberjack是一个日志滚动记录器。写入lumberjack的日志达到一定的条件后会进行存档&#xff08;普通文件的形式&#…

TAT (AYGRKKRRQRRR)

TAT (AYGRKKRRQRRR) 是一种细胞穿膜肽, 能够将各种性质的药物高效率地传递进入细胞&#xff0c;该传递过程不需要配体-受体特异性结合, 且无饱和现象。但 TAT 缺乏细胞选择性, 能够穿透所有细胞膜, 这一缺点极大地限制了其在全身给药的肿瘤靶向系统中的应用。 编号: 402555中文…

电脑麦克风没声音怎么办?3个方法快速解决

当你跟朋友电脑语音聊天的时候&#xff0c;一连说了好几段话&#xff0c;结果朋友发消息告诉你&#xff0c;问你怎么一直不吭声&#xff0c;你这才发现&#xff0c;原来是你自己电脑麦克风没声音。电脑麦克风没声音怎么办&#xff1f;电脑麦克风说话别人听不到怎么回事&#xf…

机器学习笔记之核方法(一)核方法思想与核函数介绍

机器学习笔记之核方法——核方法思想与核函数介绍引言回顾&#xff1a;支持向量机的对偶问题核方法思想介绍线性可分与线性不可分非线性带来高维转换对偶表示带来内积核函数核函数的定义(2022/11/23)正定核函数引言 本节将介绍核方法以及核函数。 回顾&#xff1a;支持向量机…