数据结构:图文详解 树与二叉树(树与二叉树的概念和性质,存储,遍历)


目录

一.树的概念

二.树中重要的概念

三.二叉树的概念

满二叉树

完全二叉树

四.二叉树的性质

五.二叉树的存储

六.二叉树的遍历

前序遍历

中序遍历 

后序遍历 


一.树的概念

树是一种非线性数据结构,它由节点和边组成。树的每个节点可以有零个或多个子节点,其中一个节点被指定为根节点。树的节点之间通过边连接。另外,树形结构中,子树之间不能有交集,否则就不是树形结构。

树的结构具有层级关系,根节点位于最顶层,而叶节点位于最底层。树的形状可以类比于现实生活中的树,根节点相当于树的根部,而分支和叶子节点则相当于树的枝干和叶子。

在计算机科学中,树被广泛用于各种应用,例如文件系统、数据库索引、编译器中的抽象语法树等。树的常见特点是具有唯一的根节点、没有循环的边、可以有任意数量的子节点等。

树的常见操作包括插入新节点、删除节点、查找节点、遍历节点等。常见的树结构包括二叉树、红黑树、AVL树等。树的设计和使用在算法和数据结构领域中非常重要,它可以提供高效的数据存储和检索方式。 


二.树中重要的概念

笔者就以下图作为例子进行说明:

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

三.二叉树的概念

二叉树是一种常见的树状数据结构,在二叉树中,每个节点最多有两个子节点,分别称为左子节点右子节点。二叉树的特点是每个节点最多只有两个子节点,且子节点的位置是有序的,即左子节点在右子节点之前。

二叉树可以为空,如果一个二叉树不为空,则它一定由根节点左子树右子树组成。每个节点都有一个值,可以是任意类型的数据。

二叉树也可以只有一个节点,如下图所示,根节点不为空,但是左子树和右子树为空,这样的二叉树也是允许存在的

总的来说,对于任意一颗二叉树,它都是由以下几部分复合而成的

二叉树可以用来表示许多实际问题,例如计算机科学中的排序和搜索算法。在二叉树中,有一些特殊的类型,如满二叉树、完全二叉树和平衡二叉树等。二叉树还可以通过遍历算法来访问其中的节点,最常见的遍历算法有前序遍历、中序遍历和后序遍历。

二叉树中还有以下俩个常见的特殊的二叉树

满二叉树

一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为 k ,且结点总数是 2^{k}-1,则它就是满二叉树。

完全二叉树

完全二叉树是由满二叉树而引出来的,对于深度为 k 的,有 n 个结点的二叉树,当且仅当其每一个结点都与深度为 k 的满二叉树中编号从0n-1的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树


四.二叉树的性质

  1. 若规定根结点的层数为1,则一棵非空二叉树的第 i 层上最多有2^{i-1}个节点
  2. 若规定只有根结点的二叉树的深度为,则深度为K的二叉树的最大结点数是2^{k}-1
  3. 对任何一棵二叉树, 如果其叶结点个数为 n0 , 度为2的非叶结点个数为 n2 ,则有 n0=n2+1 
  4.  具有 n 个结点的完全二叉树的深度 k \log _{2}^{}\textrm{}(n+1)
  5. 对于具有 n 个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为 i 的结点有:若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点;若2i+1<n,左孩子序号:2i+1,否则无左孩子;若2i+2<n,右孩子序号:2i+2,否则无右孩

五.二叉树的存储

对于任意一个节点,我们最多只能知道它的左右孩子节点和根节点,以及自己保存的数据,由此我们引申出许多种表示二叉树的方法,常见的有孩子表示法孩子双亲表示法兄弟节点表示法...

// 孩子表示法
class Node {int val; // 数据域Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}// 孩子双亲表示法
class Node {int val; // 数据域Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树Node parent; // 当前节点的根节点
}

笔者以下图举例:

 

我们使用孩子表示法,然后依次按照图示组成一颗二叉树(后文的遍历都是基于此树)

public class MyBinaryTree {public class TreeNode {public char val;//记录当前节点的值public TreeNode leftNode;//记录当前节点的左孩子节点public TreeNode rightNode;//记录当前节点的右孩子节点public TreeNode(char val) {//初始化节点的值this.val = val;}}//生成每一个节点,然后连起来public TreeNode CreatTree() {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');TreeNode H = new TreeNode('H');//依次按照图示连起来A.leftNode = B;A.rightNode = C;B.leftNode = D;C.leftNode = E;C.rightNode = F;//最后返回根节点return A;}
}

六.二叉树的遍历

二叉树的遍历是指按照一定的规则,将二叉树中的所有节点访问一次,并且每个节点只访问一次。常见的二叉树遍历方式有前序遍历中序遍历后序遍历

前序遍历

前序遍历(preorder traversal):先访问根节点,然后遍历左子树,最后遍历右子树。具体步骤如下:

  1. 访问根节点
  2. 前序遍历左子树
  3. 前序遍历右子树 

代码实现如下:

    //前序遍历public void preOrder(TreeNode root) {if (root == null) {return;//空树不需要遍历}System.out.print(root.val + " ");//访问根节点preOrder(root.leftNode);//前序遍历左子树preOrder(root.rightNode);//前序遍历右子树}

对于上述的代码,程序运行起来的具体逻辑是如下图这样的,反复的递归和回退进行实现

 

中序遍历 

中序遍历(inorder traversal):先遍历左子树,然后访问根节点,最后遍历右子树。具体步骤如下:

  1. 中序遍历左子树
  2. 访问根节点
  3. 中序遍历右子树

代码实现如下:

    //中序遍历public void inOrder(TreeNode root) {if (root == null) {return;//空树不需要遍历}inOrder(root.leftNode);//中序遍历左子树System.out.print(root.val + " ");//访问根节点inOrder(root.rightNode);//中序遍历右子树}

后序遍历 

后序遍历(postorder traversal):先遍历左子树,然后遍历右子树,最后访问根节点。具体步骤如下:

  1. 后序遍历左子树
  2. 后序遍历右子树
  3. 访问根节点

代码实现如下:

    //后序遍历public void postOrder(TreeNode root) {if (root == null) {return;//空树不需要遍历}postOrder(root.leftNode);//后序遍历左子树postOrder(root.rightNode);//后序遍历右子树System.out.print(root.val + " ");//访问根节点}

我们可以写个测试来看看遍历的结果:

public class Test {public static void main(String[] args) {MyBinaryTree myBinaryTree = new MyBinaryTree();MyBinaryTree.TreeNode rootNode = myBinaryTree.CreatTree();System.out.println();System.out.println("前序遍历:");myBinaryTree.preOrder(rootNode);System.out.println();System.out.println("中序遍历:");myBinaryTree.inOrder(rootNode);System.out.println();System.out.println("后序遍历:");myBinaryTree.postOrder(rootNode);}
}

输出:

也就是说:

其实不管是前序,中序,后序遍历,他们整体的搜索过程都是一样的,不同的地方在于对当前根节点的处理时间不一样:前序遍历是先处理根节点;中序遍历是先遍历当前节点的左子树再处理当前根节点;而后序遍历则是最后再处理根节点,就像下图一样

以上是三种最基本的二叉树遍历方式。除了这三种,还有一些其他的二叉树遍历方式,比如层序遍历螺旋遍历等。不同的遍历方式适用于不同的场景和问题,可以根据具体的需求选择合适的遍历方式。




  本次的分享就到此为止了,希望我的分享能给您带来帮助,也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深圳鼎信|输电线路防山火视频监控预警装置:森林火灾来袭,安全不留白!

受线路走廊制约和环保要求影响&#xff0c;输电线路大多建立在高山上&#xff0c;不仅可以减少地面障碍物和人类活动的干扰&#xff0c;还能提高线路的抗灾能力和可靠性。但同时也会面临其它的难题&#xff0c;例如森林火灾预防。今天&#xff0c;深圳鼎信智慧将从不同角度分析…

基于AR+地图导航的景区智慧导览设计

随着科技的飞速发展&#xff0c;智慧旅游已经成为现代旅游业的一个重要趋势。在这个背景下&#xff0c;景区智慧导览作为智慧旅游的核心组成部分&#xff0c;正逐渐受到越来越多游客的青睐。本文将深入探讨地图导航软件在景区智慧导览中的应用&#xff0c;并分析其为游客和景区…

Vue-Pinina基本教程

前言 官网地址&#xff1a;Pinia | The intuitive store for Vue.js (vuejs.org) 看以下内容&#xff0c;需要有vuex的基础&#xff0c;下面很多概念会直接省略&#xff0c;比如state、actions、getters用处含义等 1、什么是Pinina Pinia 是 Vue 的存储库&#xff0c;它允许您跨…

Graylog日志搜索技巧

graylog搜索日志用的语法是Syntax接近Lucene&#xff0c;搜起来比较方便 Search query languagehttps://go2docs.graylog.org/4-0/making_sense_of_your_log_data/writing_search_queries.html?tocpathSearching%20Your%20Log%20Data|_____1 1.Syntax 语法 1.1 基本匹配 搜…

Hive04_DDL操作

Hive DDL操作 1 DDL 数据定义 1.1 创建数据库 CREATE DATABASE [IF NOT EXISTS] database_name [COMMENT database_comment] [LOCATION hdfs_path] [WITH DBPROPERTIES (property_nameproperty_value, ...)];[IF NOT EXISTS] &#xff1a;判断是否存在 [COMMENT database_c…

【C语言】指针详解(四)

目录 1.assert断言 2.指针的使用和传址调用 2.1strlen的模拟使用 2.2传值调用和传址调用 1.assert断言 assert.h头文件定义了宏 assert()&#xff0c;用于在运行时确保程序符合指定条件&#xff0c;如果不符合&#xff0c;就报错终止运行。这个宏常常被称为“断言”。 例如…

系列十五(面试)、RocketMQ消息重复消费问题

一、RocketMQ消息重复消费问题 1.1、官网 1.2、消息重复被消费原因 通过上述官网的描述我们可以知道&#xff0c;RocketMQ中的消息是存在重复消费的情况的。那么消息为什么会被重复消费呢&#xff1f;先来回顾一下RocketMQ的消息是怎么发送和接收的&#xff1a; 从上图可以看出…

TYPE C 接口知识

1、Type C 概述 Type-C口有4对TX/RX分线&#xff0c;2对USBD/D-&#xff0c;一对SBU&#xff0c;2个CC&#xff0c;另外还有4个VBUS和4个地线。 当Type-C接口仅用作传输DP信号时&#xff0c;则可利用4对TX/RX&#xff0c;从而实现4Lane传输&#xff0c;这种模式称为DPonly模式…

概率论1:下象棋问题(3.5)

每日小语 时刻望着他人的眼色行事&#xff0c;是腾飞不了的。自己怎么想就积极地去做&#xff0c;这是需要胆量的。——广中平佑 题目 甲、乙二人下象棋&#xff0c; 每局甲胜的概率为a,乙胜的概率为b. 为简化问题&#xff0c;设没有和局的情况&#xff0c;这意味着a b1. 设想…

uni-app 命令行创建

1. 首先创建项目&#xff0c;命令如下: npx degit dcloudio/uni-preset-vue#vite-ts uni-app-demo如果出现报错&#xff0c;如下图. 大概率就是没有目录C:\Users\Administrator\AppData\Roaming\npm 解决办法&#xff1a; 创建目录 C:\Users\Administrator\AppData\Roaming\n…

有关List的线程安全、高效读取:不变模式下的CopyOnWriteArrayList类、数据共享通道:BlockingQueue

有关List的线程安全 队列、链表之类的数据结构也是极常用的&#xff0c;几乎所有的应用程序都会与之相关。在java中&#xff0c; ArrayList和Vector都使用数组作为其内部实现。两者最大的不同在与Vector是线程安全的。 而ArrayList不是。此外LinkedList使用链表的数据结构实现…

IP地址在网络安全中的关键作用

IP地址是互联网世界中的重要标识符&#xff0c;它在网络安全领域发挥着至关重要的作用。这些地址不仅帮助设备在网络上找到彼此&#xff0c;还在多个方面有助于维护网络的完整性、机密性和可用性。IP地址在网络安全中的关键作用以及实际应用有哪些呢&#xff1f; 1、身份验证和…

【自然语言处理】第2部分:识别文本中的个人身份信息

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

人工智能:网络犯罪分子的驱动力

随着 2024 年的临近&#xff0c;是时候展望今年的网络安全状况了。由于网络犯罪日益复杂&#xff0c;预计到 2025 年&#xff0c;全球网络安全成本将增至 10.5 万亿美元。 人工智能的使用不断发展&#xff0c;网络犯罪分子变得越来越有创造力 我们注意到&#xff0c;联邦调查…

sklearn 逻辑回归Demo

逻辑回归案例 假设表示 基于上述情况&#xff0c;要使分类器的输出在[0,1]之间&#xff0c;可以采用假设表示的方法。 设 h θ ( x ) g ( θ T x ) h_θ (x)g(θ^T x) hθ​(x)g(θTx)&#xff0c; 其中 g ( z ) 1 ( 1 e − z ) g(z)\frac{1}{(1e^{−z} )} g(z)(1e−z)1​…

操作无法完成(错误 0x000006ba),Windows 11 PDF打印机无法使用解决办法

操作无法完成(错误 0x000006ba)&#xff0c;Windows 11 PDF打印机无法使用解决办法 解决方式一 先重启一次电脑&#xff0c;看看是否可以解决问题。 解决方式二 重新启动 Printer Spooler 服务

Vue3中的混入(mixins)

本文主要介绍Vue3中的混入&#xff08;mixins&#xff09;。 目录 一、在普通写法中使用混入&#xff1a;二、在setup写法中使用混入&#xff1a; 混入是Vue中一种用于在组件中共享可复用功能的特性。在Vue 3中&#xff0c;混入的使用方式有所改变。 一、在普通写法中使用混入…

Java开发框架和中间件面试题(3)

14.Spring事务中的隔离级别有哪几种&#xff1f; 在TransactionDefinition接口中定义了五个表示隔离级别的常量&#xff1a; 1⃣️ISOLATION DEFAULT&#xff1a;使用后端数据库默认的隔离级别&#xff0c;Mysql默认采用的可重复读隔离级别&#xff1b;Oracle默认采用的读已提…

蓝桥杯2020年5月青少组Python程序设计国赛真题

1、 上边是一个算法流程图,最后输出的b的值是() A.377 B.987 C.1597 D.2584 2、 3、如果整个整数X本身是完全平方数,同时它的每一位数字也都是完全平方数我们就称X 是完美平方数。前几个完美平方数是0、1、4、9、49、100、144......即第1个完美平方数是0,第2个是 1,第3个…

.NET CORE 无法调试 当前不会命中断点

多个项目直接可以设置项目的属性->生成->输出的配置文件输出地址 然后路径统一输入该项目的bib/debug/.netcorex.x就可以了