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

【数据结构】二叉树的遍历以及基本操作

目录

1.树形结构

1.概念

2.二叉树

2.1概念

2.2 两种特殊的二叉树

2.3二叉树的存储

2.4二叉树的基本操作

1.手动快速创建一棵简单的二叉树

2.二叉树的遍历 (递归)

3.二叉树的层序遍历

4.获取树中节点的个数

5.获取叶子节点的个数

6.获取第K层节点的个数

7.获取二叉树的高度

8.检测值为value的元素是否存在

9.判断一棵树是不是完全二叉树


        

1.树形结构

1.概念

        树是一种非线性的数据结构
        有一个特殊的结点,称为根结点,根结点没有前驱结点
        每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
        树是递归定义的
注意:树形结构中,子树之间不能有交集,否则就不是树形结构
结点的度:当前节点子树的个数;
树的度:最大的结点的度;
叶子结点或终端结点:度为0的结点称为叶结点
父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;
子结点:一个结点含有的子树的根结点称为该结点的子结点;
根结点:没有前驱的结点
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推
树的高度或深度:树中结点的最大层次;

2.二叉树

2.1概念

1. 二叉树不存在度大于2的结点
2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

2.2 两种特殊的二叉树

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

2.3二叉树的存储

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

2.4二叉树的基本操作

1.手动快速创建一棵简单的二叉树

 

public Node TreeBuild(){Node node1 = new Node('A');Node node2 = new Node('B');Node node3 = new Node('C');Node node4 = new Node('D');Node node5 = new Node('E');Node node6 = new Node('F');Node node7 = new Node('G');Node node8 = new Node('H');Node node9 = new Node('I');Node node10 = new Node('J');Node node11 = new Node('K');node1.left = node2;node1.right = node3;node2.left = node4;node2.right = node5;node3.left = node6;node3.right = node7;node4.left = node8;node4.right = node9;node5.right = node10;node6.right = node11;return node1;}

2.二叉树的遍历 (递归)

·   //前序遍历public void preOrder(Node root){if(root == null){return ;}System.out.print(root.val+" ");preOrder(root.left);preOrder(root.right);}//中序遍历public void inOrder(Node root){if(root == null){return;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}//后序遍历public void postOrder(Node root){if(root == null){return;}postOrder(root.left);postOrder(root.right);System.out.print(root.val+" ");}

3.二叉树的层序遍历

    //层序遍历public List<List<Character>> levelOrder(Node root){//创建一个二维数组保存每一层的元素List<List<Character>> list = new ArrayList<>();if(root == null){return list;}//临时队列Deque<Node> deque = new LinkedList<>();//头节点放入队列deque.offer(root);//队列非空进循环while(!deque.isEmpty()){int size = deque.size();List<Character> curList = new ArrayList<>();for (int i = 0; i < size; i++){Node x = deque.pop();//左子树不为空,左子树入队列if(x.left != null){deque.offer(x.left);}//右子树不为空,右子树入队列if(x.right != null){deque.offer(x.right);}//出栈的元素值存放在临时数组里curList.add(x.val);}//出循环将临时数组加入二维数组list.add(curList);}return list;}

4.获取树中节点的个数

    public int size(Node root){if(root == null){return 0;}return 1 + size(root.left) + size(root.right);}

5.获取叶子节点的个数

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

6.获取第K层节点的个数

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

7.获取二叉树的高度

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

8.检测值为value的元素是否存在

    // 检测值为value的元素是否存在public boolean find(Node root, int val){if(root == null){return false;}if(root.val == val){return true;}return find(root.left,val) || find(root.right,val);}

9.判断一棵树是不是完全二叉树

    // 判断一棵树是不是完全二叉树boolean isCompleteTree(Node root){if(root == null){return true;}//队列为空出循环,两个阶段//1.所有都是度为2的节点//2.碰到第一个度为1的节点,右节点直接false,左节点进入第二阶段//碰到第一个度为0的节点,进入第二阶段//3。第二阶段,都是叶子节点,如果有不是叶子节点,直接falseDeque<Node> deque = new LinkedList<>();deque.offer(root);boolean flag = true;while(!deque.isEmpty()){if(flag){Node x = deque.poll();if(x.left != null && x.right != null){deque.offer(x.left);deque.offer(x.right);}else if(x.right != null){return false;}else if(x.left != null){deque.offer(x.left);flag = false;}else {flag = false;}}else {Node x = deque.poll();if(x.left != null || x.right != null){return false;}}}return true;}

相关文章:

【数据结构】二叉树的遍历以及基本操作

目录 1.树形结构 1.概念 2.二叉树 2.1概念 2.2 两种特殊的二叉树 2.3二叉树的存储 2.4二叉树的基本操作 1.手动快速创建一棵简单的二叉树 2.二叉树的遍历 (递归) 3.二叉树的层序遍历 4.获取树中节点的个数 5.获取叶子节点的个数 6.获取第K层节点的个数 7.获取二叉…...

若依框架 --- ruoyi 表格的设置

表格 字典值转换 (1) 方式1&#xff1a;使用字典枚举的方式 var isDownload [[${dict.getType(YES_OR_NO)}]];{field : isDownload,title : 是否允许下载,formatter: function(value, row, index) {return $.table.selectDictLabel(isDownload, value);} }, (2) 方式2&…...

“两会”网络安全相关建议提案回顾

作为新一年的政治、经济、社会等发展的“风向标”&#xff0c;今年“两会”在3月13日顺利闭幕。在今年“两会”期间&#xff0c;多位人大代表也纷纷围绕网络安全、数据安全的未来发展做了提案和建议。 01 “两会”网络安全相关建议和提案回顾 建议统筹智能网联汽车数据收集与共…...

一篇文章带你真正了解接口测试(附视频教程+面试真题)

目录 一、什么是接口测试&#xff1f; 二、为什么要做接口测试&#xff1f; 三、如何开展接口测试&#xff1f; 四、接口测试常见面试题 一、什么是接口测试&#xff1f; 所谓接口&#xff0c;是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据…...

C/C++每日一练(20230325)

目录 1. 搜索插入位置 &#x1f31f; 2. 结合两个字符串 &#x1f31f; 3. 同构字符串 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 搜索插入位置 给定一个排序数…...

Linux操作系统ARM指令集与汇编语言程序设计

一、实验目的1.了解并掌握ARM汇编指令集2.应用ARM指令集编写一个程序操控开发板上的LED灯二、实验要求应用ARM汇编指令集编写程序&#xff0c;实现正常状态下开发板上的LED灯不亮&#xff0c;按下一个按键之后开发板上的LED灯进入流水灯模式。三、实验原理四个LED灯的电路如下图…...

计网之HTTP协议和Fiddler的使用

文章目录一. HTTP概述和fidder的使用1. 什么是HTTP2. 抓包工具fidder的使用2.1 注意事项2.2 fidder的使用二. HTTP协议格式1. HTTP请求格式1.1 基本格式1.2 认识URL1.3 方法2. 请求报头关键字段3. HTTP响应格式3.1 基本格式3.2 状态码一. HTTP概述和fidder的使用 1. 什么是HTT…...

sql性能优化:MS-SQL(SQL Server)跟踪日志信息结果列字段说明,MSSQL的列字段说明(column)

sql性能优化&#xff1a;MS-SQL&#xff08;SQL Server&#xff09;跟踪日志信息结果列字段说明&#xff0c;MSSQL的列字段说明&#xff08;column&#xff09; 参考&#xff1a; SQL:BatchCompleted 事件类 | Microsoft Learn SQL 跟踪 | Microsoft Learn sp_trace_setevent (…...

DNS主从复制

#前提准备&#xff1a;关闭SElinux 关闭防火墙 时间同步 #环境说明&#xff1a;Centos7 #ip地址&#xff1a;dns-master&#xff1a;10.0.0.100 dns-slave&#xff1a;10.0.0.103 web&#xff1a;10.0.0.101 主DNS服务配置 1.安装软件包&#xff1a; yum install bind -…...

常见的js加密/js解密方法

常见的js加密/js解密方法 当今互联网世界中&#xff0c;数据安全是至关重要的。为了保护用户的隐私和保密信息&#xff0c;开发人员必须采取适当的安全措施。在前端开发中&#xff0c;加密和解密技术是一种常见的数据安全措施&#xff0c;其中 JavaScript 是最常用的语言之一。…...

6 python函数

函数 在实现某个功能对应的代码的时候&#xff0c;如果将实现功能对应的函数放到函数中&#xff0c;那么下一次再需要这个功能的时候&#xff0c;就可以不用再写这个功能对应的代码&#xff0c;直接调用这个功能对应的函数。 1.什么是函数 函数就是实现某一特点功能的代码的封装…...

7.避免不必要的渲染

目录 1 组件更新机制 2 虚拟DOM配合Diff算法 3 减轻state 4 shouldComponentUpdate() 4.1 基本使用 4.2 使用参数 5 纯组件 5.1 基本使用 5.2 纯组件的比较方法 shallow compere 1 组件更新机制 当父组件重新渲染时&#xff0c;父组件的所有子组件也会重新…...

国产化大趋势下学习linux的必要性

由于国际上的一些国家的制裁和威胁。最近几年国产化大趋势慢慢的兴起&#xff0c;我们国产化硬件的需求越来越大。对国产操作系统的需求也越来越多&#xff0c;那么我们一直用的Windows系统为什么不用了呢&#xff1f;众所周知的原因&#xff0c;不管是最新的Windows11还是正值…...

浅谈虚树

问题引入 你是否遇到过下面这种问题&#xff1a; SDOI2011 消耗战 在一场战争中&#xff0c;战场由 nnn 个岛屿和 n−1n-1n−1 个桥梁组成&#xff0c;保证每两个岛屿间有且仅有一条路径可达。现在&#xff0c;我军已经侦查到敌军的总部在编号为1的岛屿&#xff0c;而且他们已…...

裸机条件下写一个基于时间片轮转的多任务并发程序

目录前言A. 使用RTOSB.裸机多任务并发前言 在学习各种MCU的时候&#xff0c;都是用在main函数里写一个while(1){/* 执行代码 */}&#xff0c;这种方式只能一个函数运行完以后再运行另一个函数。 假设需求控制多个模块&#xff0c;如显示屏幕信息的同时控制电机&#xff0c;还要…...

RK3588 系统定制开关机动画

平台&#xff1a;ITX-3588J, ROC-RK3588S-PC 系统&#xff1a;Android12.0 作者&#xff1a;jpchen & zzz 一. 功能描述 定制自己的开机动画和关机动画 二. 功能实现 1.开启功能 修改device/rockchip/common/BoardConfig.mk文件 BOOT_SHUTDOWN_ANIMATION_RINGINGtrue2.…...

水文-编程命令快查手册

前言 脑子里面记不住一些命令&#xff0c;每次遇到都得查下。我经常在三个实体电脑&#xff0c;windows/uos/ubuntu不同系统上编程。 所以web版本的笔记查看起来方便点。这里报错下。 二级标题 cmake windows在cmake --build的时候&#xff0c;使用–config&#xff0c;指定…...

如何优雅编写测试用例

当你学会了如何设计测试用例之后&#xff0c;接下来便是开始用例的编写。 在设计阶段&#xff0c;更准确的说应该是识别测试点的过程&#xff0c;而编写阶段则是将测试点细化成一条条测试用例的过程&#xff0c;有了比较全的用例场景后&#xff0c;如何让别人更舒服、更方便、…...

[入门必看]数据结构2.3:线性表的链式表示

[入门必看]数据结构2.3&#xff1a;线性表的链式表示第二章 线性表2.3 线性表的链式表示知识总览2.3.1 单链表的定义2.3.2_1 单链表的插入删除2.3.2_2 单链表的查找2.3.2_3 单链表的建立2.3.3 双链表2.3.4 循环链表2.3.5 静态链表2.3.6 顺序表和链表的比较2.3.1 单链表的定义单…...

Golang流媒体实战之二:回源

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 今天的实战是流传输过程中的常见功能&#xff1a;回源如下图&#xff0c;lal(源站)和lal(拉流节点)代表两台电脑&#xff0c;上面都部署了lalVLC在…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...