二叉树详细介绍与代码生成遍历

目录

  • 树的概念及其结构
    • 树的构造——代码表示
  • 二叉树概念及介绍
  • 二叉树的存储结构
    • 二叉树的顺序结构
    • 二叉树的链式结构
    • 链表的代码展示
    • 堆的基本概念和结构
    • 堆的代码体现
    • 二叉树生成
    • 二叉树遍历
  • 四种不同遍历方式——代码展示

树的概念及其结构

要了解二叉树,那么首要的就是要知道树的概念。
在这里插入图片描述

在计算机科学中,树是一种广泛使用的抽象数据类型,用于模拟层次结构,树由节点构成。在这种层级系统中,存在一个最顶层的节点,称为根节点,它没有父节点。树中的其他节点可以有一个(在非二叉树中)或多个子节点,但只有一个父节点,除了根节点外。

树结构的基本术语:

  • 节点(Node): 树的基本部分,可能包含一个值或数据,并可能有子节点。
  • 根节点(Root): 树的顶端节点,没有父节点。
  • 叶子节点(Leaf nodes): 没有子节点的节点。
  • 子节点(Child nodes): 某个节点的直接后继节点。
  • 父节点(Parent node): 某个节点的直接前驱节点。
  • 兄弟节点(Sibling nodes): 具有相同父节点的节点。
  • 边(Edge): 连接节点的线,它定义了节点之间的父子关系。
  • 路径(Path): 从一个节点到另一个节点的边的序列。
  • 深度(Depth): 从根节点到某个节点的边的数目。
  • 高度(Height): 一个节点到最远叶子节点的最长路径的边的数目。树的高度是其所有节点高度的最大值。

下图是树的结构示意图
在这里插入图片描述
树结构没有循环或闭环,这是它和图结构的主要区别,如下就不能称作是树结构,因为子树之间有相交。
在这里插入图片描述

树的构造——代码表示

class TreeNode:def __init__(self, value):self.value = value  # 当前节点的值self.children = []  # 子节点的列表def add_child(self, child_node):"""添加子节点"""self.children.append(child_node)def remove_child(self, child_node):"""移除子节点"""self.children = [child for child in self.children if child is not child_node]def traverse(self):"""遍历树节点"""nodes_to_visit = [self]while len(nodes_to_visit) > 0:current_node = nodes_to_visit.pop()print(current_node.value)nodes_to_visit.extend(current_node.children)# 示例构造树
root = TreeNode('Root')
child1 = TreeNode('Child1')
child2 = TreeNode('Child2')
child3 = TreeNode('Child3')root.add_child(child1)
root.add_child(child2)
child1.add_child(child3)# 遍历和打印树
root.traverse()

上述代码定义了一个树节点,它包含一个值和一个子节点列表。并且可以添加或移除子节点,并有一个用于遍历树的方法,它采用深度优先遍历(Depth-First Search, DFS)的方式来访问每个节点。

这个例子中构建的树结构如下所示:
在这里插入图片描述
当运行 root.traverse() 方法时,它会打印出:

Root
Child1
Child3
Child2

这不是二叉树,因为每个节点可以有任意数量的子节点。 若要创建一个二叉树的结构,你需要为每个节点定义两个指定的子节点属性,通常是 left 和 right。

二叉树概念及介绍

二叉树是一种重要的数据结构,在计算机科学中广泛应用于各类算法中。二叉树是由节点组成的,每个节点最多有两个子节点,分别称为左子节点和右子节点。

二叉树的类别:

1、完全二叉树(Complete Binary Tree): 除了最后一层外,每一层都被完全填满,最后一层的所有节点都尽可能地靠左排列。
在这里插入图片描述
2、满二叉树(Full Binary Tree): 每个节点要么没有子节点,要么有两个子节点。

在这里插入图片描述

3、平衡二叉树(Balanced Binary Tree): 任意两个叶子节点之间的高度差最多为一,即两个子树的高度差都可以是 -1,0 或 1。最常见的平衡二叉树是 AVL 树。

所有的平衡二叉树都满足二叉搜索树的条件。平衡条件确保了树的深度最大只能是 O(log n)(n为节点数量),这有助于防止树的一侧异常过长,导致操作效率下降。

一个平衡二叉树的结构示例(AVL 树):
在这里插入图片描述

在这个 AVL 树中,任何一个节点的左右子树高度差都不超过 1,这意味着它是平衡的。

在此,我们展示一个不是平衡二叉树的结构:
在这里插入图片描述

平衡二叉树是为了解决普通二叉搜索树在极端情况下会退化成链表,从而导致效率下降的问题。二叉搜索树如果不平衡,它的操作(查找、插入、删除等)的时间复杂度在最坏的情况下可以变成O(n)。而平衡二叉树通过旋转操作来保持平衡,确保操作的时间复杂度稳定在 O(log n)

4、二叉搜索树(Binary Search Tree, BST): 满足以下性质的二叉树:

  • 每个节点的左子树只包含小于当前节点的数。
  • 每个节点的右子树只包含大于当前节点的数。
  • 所有左右子树也必须是二叉搜索树。
    在这里插入图片描述

二叉树的存储结构

二叉树一般可以使用两种存储结构,一种顺序结构,一种链式结构。

二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。我们通常把这种完全二叉树使用顺序结构的数组来存储。
在这里插入图片描述
而这种存储又称作堆,这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

二叉树的链式结构

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,遇到的一般都是二叉链。

在这里插入图片描述

链表的代码展示

二叉链表的定义:

class BinaryTreeNode:def __init__(self, value):self.value = valueself.left = Noneself.right = None# 示例创建二叉链表节点
root = BinaryTreeNode('A')
root.left = BinaryTreeNode('B')
root.right = BinaryTreeNode('C')

三叉链表的定义:

class TernaryTreeNode:def __init__(self, value):self.value = valueself.left = Noneself.right = Noneself.parent = None# 生成三叉链表节点并建立连接
root = TernaryTreeNode('A')
node_b = TernaryTreeNode('B')
node_c = TernaryTreeNode('C')root.left = node_b
root.right = node_c
node_b.parent = root
node_c.parent = root

堆的基本概念和结构

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
在这里插入图片描述

堆的性质:
1、堆中某个节点的值总是不大于或不小于其父节点的值;
2、堆总是一棵完全二叉树。

堆的代码体现

小根堆展示:

import heapq# 创建小根堆
min_heap = []
heapq.heappush(min_heap, 3)
heapq.heappush(min_heap, 1)
heapq.heappush(min_heap, 2)# 从堆中弹出最小元素
print(heapq.heappop(min_heap))  # 输出 1
print(heapq.heappop(min_heap))  # 输出 2
print(heapq.heappop(min_heap))  # 输出 3

大根堆展示:

import heapq# 创建大根堆的辅助函数
def heappush_max(heap, item):heapq.heappush(heap, -item)def heappop_max(heap):return -heapq.heappop(heap)# 创建大根堆
max_heap = []
heappush_max(max_heap, 3)
heappush_max(max_heap, 1)
heappush_max(max_heap, 2)# 从堆中弹出最大元素
print(heappop_max(max_heap))  # 输出 3
print(heappop_max(max_heap))  # 输出 2
print(heappop_max(max_heap))  # 输出 1

在这两个例子中,小根堆可以直接通过 heapq 提供的函数 heappush 和 heappop 来操作,而大根堆则通过取反的方式使用了相同的函数。

当想将元素添加到大根堆时,可以使用 heappush_max 函数;并且当想从大根堆中弹出最大元素时,可以使用 heappop_max 函数。通过取反操作,能够保持堆的性质而适用于 heapq的小根堆实现。

二叉树生成

生成二叉树通常是指创建二叉树的过程。二叉树可以通过多种方式生成,例如:递归地构建、从数组构建、通过用户输入构建等。二叉树的生成通常包括初始化根节点以及递归或迭代地添加子节点至适当位置。
在这里插入图片描述

二叉树遍历

遍历二叉树是指按照某种顺序访问二叉树中的每一个节点,确保每个节点被访问一次。通常有以下几种遍历方法:

  1. 前序遍历(Pre-order Traversal):

    • 访问根节点
    • 遍历左子树
    • 遍历右子树
    • 可用于打印树结构,复制树结构等。
  2. 中序遍历(In-order Traversal):

    • 遍历左子树
    • 访问根节点
    • 遍历右子树
    • 对于二叉搜索树(BST),这种遍历方式会按照节点的升序排列访问它们。
  3. 后序遍历(Post-order Traversal):

    • 遍历左子树
    • 遍历右子树
    • 访问根节点
    • 常用于删除或释放树中的节点,因为它确保节点在其子节点被访问后才被访问。
  4. 层序遍历(Level-order Traversal):

    • 按照树的层级从上至下访问节点
    • 通常使用队列来辅助实现
    • 也被称为广度优先搜索(BFS, Breadth-First Search)

每种遍历方式都有其特定的用途,并且可以递归或迭代地实现。访问节点的具体操作可以根据需要进行变化,例如打印节点值、计算树的深度,或者累加节点值等。

四种不同遍历方式——代码展示

我们通过0-9这10个数字进行展示说明:

# 二叉树的节点类
class btree_node():# 初始化节点,每个节点有三个属性:节点值、节点左子树、节点右子树def __init__(self,val):#节点幅值self.data=val# 节点左子树self.left=None# 节点右子树self.right=None# 定义二叉树类
class binary_Tree():def __init__(self):self.tree_struct=None# 增加节点,这个函数也是建树的过程def add_node(self,new_node):# 将树的结构放到列表中list_nodes=[self.tree_struct]# 如果是孔数,直接在书上加上这个节点if self.tree_struct==None:# 在空树上加上节点self.tree_struct= new_nodereturn#在循环前list_nodes只有一棵树,在循环中间list_nodes中追加了这棵树的子树。while len(list_nodes)>0:# 从列表中弹出提排在最前面的树cur_node=list_nodes.pop(0)# 如果树的左子树为空,把该节点当作该树的左子树if cur_node.left==None:# 让新结点成为树的左子树cur_node.left=new_nodereturnelse:# 如果树的左子树不为空,则把这棵树的左子树追加到列表后面list_nodes.append(cur_node.left)# 如果树的右子树为空,把新结点当作该数的右子树if cur_node.right==None:# 让新结点成为树的右子树cur_node.right=new_nodereturnelse:# 如果树的右子树不为空,把这个树的右子树加到列表后面list_nodes.append(cur_node.right)# 广度遍历,从树的顶层,一层层遍历,每一层从左到右取各结点数值def breadth_travel(self):# 如果是空树直接返回if self.tree_struct == None:return# 将树的结构放到列表中list_nodes = [self.tree_struct]# 以下循环主要流程是:# 每次从列表中弹出最前面的一个树(第一次弹出的是整个树,以后是弹出的是子树),# 打印这个树根结点的值,# 先看一下这个树的左孩子(左子树)是否为空,不为空,# 把该树的左孩子(左子树)追加到列表后面,# 再看一下这个树的右孩子(右子树)是否为空,# 不为空,把该树的右孩子(右子树)追加到列表后面,# 进入下一次循环,再次从列表最前面弹出一个树(子树)while len(list_nodes) > 0:cur_node = list_nodes.pop(0)print(cur_node.data, end='')if cur_node.left != None:list_nodes.append(cur_node.left)if cur_node.right != None:list_nodes.append(cur_node.right)# 先序遍历,按照根节点、左子树、右子树的顺序访问二叉树# 第1步:访问根节点(或子树根节点);# 第2步:递归调用本函数遍历左子树;# 第3步:递归调用本函数遍历右子树。def pre_travel(self, tree_node):# 如果树为空直接返回if tree_node == None:return# 打印出当前树根结点的值print(tree_node.data, end='')# 对左子树递归调用self.pre_travel(tree_node.left)# 对右子树递归调用self.pre_travel(tree_node.right)# 中序遍历:按照左子树、根节点、右子树的顺序访问# 第1步:递归调用本函数遍历左子树;# 第2步:访问根节点(或子树根节点);# 第3步:递归调用本函数遍历右子树。def midd_travle(self, tree_node):# 如果树为空直接返回if tree_node == None:return# 对左子树递归调用self.midd_travle(tree_node.left)# 打印出当前树根结点的值print(tree_node.data, end='')# 对右子树递归调用self.midd_travle(tree_node.right)# 后序遍历:按照左子树、右子树、根节点的顺序访问# 第1步:递归调用本函数遍历左子树;# 第2步:递归调用本函数遍历右子树;# 第3步:访问根节点(或子树根节点)。def back_travel(self, tree_node):# 如果树为空直接返回if tree_node == None:return# 对左子树递归调用self.back_travel(tree_node.left)# 对右子树递归调用self.back_travel(tree_node.right)print(tree_node.data, end='')# 主程序main
if __name__ == "__main__":tree = binary_Tree()for i in range(10):new_node = btree_node(i)tree.add_node(new_node)print('广度遍历结果:', end='')tree.breadth_travel()print('')print('前序遍历结果:', end='')tree.pre_travel(tree.tree_struct)print('')print('中序遍历结果:', end='')tree.midd_travle(tree.tree_struct)print('')print('后序遍历结果:', end='')tree.back_travel(tree.tree_struct)

运行结果展示:
在这里插入图片描述

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

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

相关文章

Spark Structured Streaming 分流或双写多表 / 多数据源(Multi Sinks / Writes)

博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,…

探索潜力:中心化交易所平台币的对比分析

核心观点 平台币在过去一年里表现差异显著: 在过去的一年里,只有少数几个平台币如BMX、BGB和MX的涨幅超过了100%。相比之下,由于市值较高,BNB和OKB的涨幅相对较低。 回购和销毁机制在平台币价值中起决定性作用: 像M…

2024五一数学建模竞赛(五一赛)选题建议+初步分析

提示&#xff1a;DS C君认为的难度&#xff1a;B>A>C&#xff0c;开放度&#xff1a;AB<C。 以下为A-C题选题建议及初步分析&#xff1a; A题&#xff1a;钢板最优切割路径问题 l 难度评估&#xff1a;中等难度。涉及数学建模和优化算法&#xff0c;需要设计最优的…

前后端数据加密代码实战(vue3.4+springboot 2.7.18)

简述&#xff1a; 文章主要讲述了在vue3与springboot交互数据的个人使用的一个加密形式 SHA256不可逆加密AES对称加密RSA非对称加密 加密算法就不带大家深入了&#xff0c;对于它的使用文章中有明确的案例 数据加密的大概流程为&#xff1a;&#xff08;有更优秀的方案可以…

Springboot+Vue项目-基于Java+MySQL的入校申报审批系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Python用KNN处理缺失值(4月30-5月1日)

首先试验KNN的简单示例代码 #方法3&#xff1a; # 本论文拟采用的填充缺失值的方法为KNN: import pandas as pd from sklearn.impute import KNNImputer #创建一个包含缺失值的数据集 data_KNN{第一列:[1,2,None,4,5],第二列:[3,None,5,7,9],第三列:[2,4,6,None,10] } dfpd.Da…

有哪些ai自动生成图片软件?AI绘画工具推荐

AI绘画工具是近年来快速发展的一种创新技术&#xff0c;它可以通过算法和机器学习技术来自动生成图片。那么又有有哪些ai自动生成图片软件呢&#xff1f;下面是小编给大家的AI绘画工具推荐。 一、爱制作AI 爱制作AI是一款多功能的人工智能助手&#xff0c;具备AI问答、AI写作、…

【FPGA】优化设计指南(一):设计原则

目录 避免采用不可综合的语句设计时采用同步的时钟组合逻辑与毛刺异步复位与同步复位动态分析与静态分析功能流水线时序违例乒乓操作面积和速度的平衡避免采用不可综合的语句 1.#1000延时语句 2.除法运算/,除非除数为2的整次幂 3.实数类型不可综合(real) 4.综上,使用可综合…

STM32进入睡眠模式的方法

#STM32进入睡眠模式的方法 今天学习了如何控制STM32进入睡眠模式&#xff0c;进入睡眠模式的好处就是省电&#xff0c;今天学习的只是浅度睡眠&#xff0c;通过中断就能唤醒。比如单片机在那一放&#xff0c;也许好几天好几个月都不用一次&#xff0c;整天的在那空跑while循环…

C#应用程序实现多屏显示

前言 随着业务发展&#xff0c;应用程序在一些特定场景下&#xff0c;只在一个显示器上展示信息已经不能满足用户需求。我们如何把主屏运行程序中多个窗体移动到各个扩展屏幕位置显示呢&#xff1f;C# 是通过什么方式来实现的&#xff0c;下面介绍 C# 使用 Screen 类的方式来实…

64、二分-搜索二维矩阵

思路&#xff1a; 通过使用二分方式&#xff0c;对于每行进行二分&#xff0c;因为每行的最后一个数小于下一行的第一个数&#xff0c;我们就可以依次二分。首先取出行数N&#xff0c;然后从0-N进行二分&#xff0c;如果mid最后一个数小于目标值说明0-mid中没有&#xff0c;舍弃…

jenkins转载文本

基于Docker容器DevOps应用方案 企业业务代码发布系统 一、企业业务代码发布方式 1.1 传统方式 以物理机或虚拟机为颗粒度部署部署环境比较复杂&#xff0c;需要有先进的自动化运维手段出现问题后重新部署成本大&#xff0c;一般采用集群方式部署部署后以静态方式展现 1.2 容…

鸿蒙开发接口Ability框架:【@ohos.ability.wantConstant (wantConstant)】

wantConstant wantConstant模块提供want中action和entity的权限列表的能力&#xff0c;包括系统公共事件宏&#xff0c;系统公共事件名称等。 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导…

基于电磁激励原理利用视触觉传感器估计抓取力矩的方法

由于触觉感知能使机器人通过其触觉传递获取丰富的接触信息&#xff0c;触觉感知已经成为机器人机械臂的一种流行的感知方式。而在触觉传感器可获取的各种信息中&#xff0c;通过外界接触从抓取物体传递到机器人手指的力矩等信息&#xff0c;在完成各种指令的实现尤为重要。如图…

可重构柔性装配产线:AI边缘控制技术的崭新探索

在信息化和智能化浪潮的推动下&#xff0c;制造业正面临着前所未有的转型升级挑战。其中&#xff0c;可重构柔性装配产线以其独特的AI边缘控制技术&#xff0c;为制造业的智能化转型提供了新的解决方案。 可重构柔性装配产线是基于AI工业控制与决策平台打造的智能化生产系统。…

Spring Security介绍(三)过滤器(2)自定义

除了使用security自带的过滤器链&#xff0c;我们还可以自定义过滤器拦截器。 下面看下自定义的和security自带的执行顺序。 一、总结 1、自定义过滤器&#xff1a; 一般自定义fliter都是&#xff1a; import lombok.extern.slf4j.Slf4j; import org.springframework.ster…

QT - 创建Qt Widgets Application项目

在Qt中结合OpenGL使用&#xff0c;可以创建一个Qt Widgets应用程序项目。在创建项目时&#xff0c;您可以选择使用OpenGL模板来生成一个已经集成了OpenGL的项目。这个模板会自动帮助您集成OpenGL和Qt&#xff0c;并生成一个基本的OpenGL窗口。您可以在这个窗口中进行OpenGL的开…

闭嘴,如果你遇到偏执型人格!头脑风暴:王阳明心学向内求——早读(逆天打工人爬取热门微信文章解读)

看我极限头脑风暴 引言Python 代码第一篇 洞见 偏执型人格&#xff1a;跟谁在一起&#xff0c;谁痛苦第二篇 人民日报 来啦新闻早班车要闻社会政策 结尾 若天意未许晴好时&#xff0c; 勿将雨声作悲泣。 不向外界寻怨尤&#xff0c; 反求诸己养性灵。 引言 五一劳动节 第一天就…

C语言(操作符)1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

区块链论文总结速读--CCF B会议 ICDCS 2023 共8篇

Conference&#xff1a;IEEE 43rd International Conference on Distributed Computing Systems (ICDCS) CCF level&#xff1a;CCF B Categories&#xff1a;Computer Architecture/Parallel and Distributed Computing/Storage Systems 计算机体系结构/并行与分布计算/存储…