树和二叉树(一)

news2024/11/21 17:03:19

一、树

      非线性数据结构,在实际场景中,存在一对多,多对多的情况。

 

树( tree)是n (n>=0)个节点的有限集。当n=0时,称为空树。

在任意一个非空树中,有如下特点。

1.有且仅有一个特定的称为根的节点。

2.当n>1时,其余节点可分为m (m>0)个互不相交的有限集,每一个集合本身又是一个树,并称为根的子树。 

如图所示:节点1:根节点(root),节点5,6,7,8:叶子节点(leaf);分为不同的层级,节点4是父节点(parent),节点4的孩子节点(child)节点4的兄弟节点(sibling);

 

树的最大的层级树,称为数的高度或深度,上图的数的高度为4。 

二、 二叉树

     二叉树(binary tree)是树的一种特殊形式。二叉顾名思义,这种树的每个节点最多有2个孩子节点

   注意:这里是最多有2个,也可能只有1个,或者没有孩子节点。 

 

二叉树节点的两个孩子节点,一个被称为左孩子(leftchild) ,一个被称为右孩子(right child)。

此外,二叉树还有两种特殊形式,一个叫作满二叉树,另一个叫作完全二叉树

2.1、二叉树的五种基本形式: 

2.2、二叉树与树的区别 :

  • 树中结点的最大度数没有限制,而二叉树结点的最大度数为2
  • 树的结点无左、右之分,而二叉树的结点有左、右之分

2.3、满二叉树与完全二叉树:

(1)满二叉树

     一个二叉树的所有非叶子节点都存在左孩子和右孩子,并且所有叶子节点都在同一层级上,那么这个树就是满二叉树。 

简单点说,满二叉树的每一个分支都是满的。


 

 (2)完全二叉树

     对一个有n个节点的二叉树,按层级顺序编号,则所有节点的编号为从1到n。如果这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同,则这个二叉树为完全二叉树。

 

     在上图中,二叉树编号从1到12的12个节点,和前面满二叉树编号从1到12的节点位置完全对应。因此这个树是完全二叉树。 

      完全二叉树的条件没有满二叉树那么苛刻:满二叉树要求所有分支都是满的;而完全二叉树只需保证最后一个节点之前的节点都齐全即可。  

三、二叉树的性质 

1、在二叉树的第 i 层上最多有 2^n-1个结点(i>=1) 

2、深度(高度)为 k 的二叉树最多有 2^k - 1个结点(k>=1)

 

3、对任意一颗二叉树,如果其叶子节点数为 N0,度为2的结点数为N2,则 N0 = N2 + 1 

设 : 结点之间的总连线数是B ,总结点数是n,
        度为0的结点是n0,
        度为1的结点是n1,
        度为2的结点是n2, 

      从上往下看 二叉树最大的度就是2所以的节点要么度是2,要么度是1,要么度是0,度是2的会发出两条线, 度是1的发出1条线所以得到图片里的公式 B = n2 * 2 + n1;

二叉树的总结点数 n = n1 +n2+n0;

总连续数 B=n-1

 

由此得出:度是0的结点个数=度是2的结点个数+1

四、二叉树的存储

1.链式存储结构

2.数组

 (1)链式存储结构

  

  • 存储数据的data变量
  • 指向左孩子的left指针
  • 指向右孩子的right指针

(2)数组

        使用数组存储时,会按照层级顺序把二叉树的节点放到数组中对应的位置上。如果某一个节点的左孩子或右孩子空缺,则数组的相应位置也空出来。

 如何方便地在数组中定位二叉树的孩子节点和父节点?

     假设一个父节点的下标是parent,

     左孩子节点的下标=2xparent +1;

     右孩子节点的下标=2xparent+2。

由此:

     如果一个左孩子节点的下标是leftChild,那么它的父节点下标=(leftChild-1)/2。

     如果一个右孩子节点的下标是rightChild,那么它的父节点下标=(rightChild-2)/2。

  

 图上所示, 节点5的索引是4,那么节点5的父节点=(4-2)/2=1,由此可得索引1对应的是节点2

五、二叉树的遍历

  1. 深度优先遍历
  2. 广度优先遍历

1. 深度优先遍历
    深度优先( depth first search,DFS ) ,顾名思义就是偏向于纵深,“一头扎到底”的访问方式。深度优先遍历又根据遍历顺序的不同分为三种:前序遍历、中序遍历、后序遍历

1.1 前序遍历
所谓前序遍历,是指二叉树遍历每个子树的时候,都是按照根结点、左子树、右子树的顺序来遍历,因为根结点在前,所以叫做前序遍历。前序遍历中根结点的优先级别最高。如下图所示:

1.2 中序遍历

如果二叉树遍历每个子树的时候,都是按照左子树、根结点、右子树的顺序来遍历,因为根结点在中间,所以叫做中序遍历。如下图所示:

1.3 后序遍历

二叉树遍历每个子树的时候,都是按照左子树、右子树、根结点的顺序来遍历,因为根结点在最后,所以叫做后序遍历。如下图所示:

 使用递归的方式来操作,如图所示

''''树节点'''
class TreeNode:
    '''初始化'''
    def __init__(self,data):
        self.data=data #数据
        self.left=None #左节点
        self.right=None #右节点

'''二叉树'''
class MyTree:
    def create_tree(self,input_list=[]):
        #判断数列是否为空
        if input_list is None or len(input_list)==0:
            return None
        #第一个出队
        data=input_list.pop(0)
        #判断数据为空
        if data is None:
            return None
        #树节点
        node=TreeNode(data)
        #创建左节点
        node.left=self.create_tree(input_list)
        #创建右节点
        node.right =self.create_tree(input_list)
        return node

    def before_foreach(self,node):
        '''
        前序遍历  (根左右)
        :param node:  二叉树节点
        :return:
        '''
        # 判断节点为空
        if node is None:
            return None
        #显示节点数据
        print(node.data,end=',')
        #再次遍历左节点,右节点
        self.before_foreach(node.left)
        self.before_foreach(node.right)
        return node

    def middle_foreach(self,node):
        '''
        中年序遍历  (左根右)
        :param node:  二叉树节点
        :return:
        '''
        # 判断节点为空
        if node is None:
            return None
        #再次遍历左节点
        self.middle_foreach(node.left)
        # 显示节点数据
        print(node.data, end=',')
        # 再次遍历右节点
        self.middle_foreach(node.right)
        return node

    def after_foreach(self,node):
        '''
        后序遍历  (左右根)
        :param node:  二叉树节点
        :return:
        '''
        # 判断节点为空
        if node is None:
            return None
        #再次遍历左节点,右节点
        self.after_foreach(node.left)
        self.after_foreach(node.right)
        # 显示节点数据
        print(node.data, end=',')
        return node


if __name__ == '__main__':
    #二叉树对象
    my=MyTree()
    #列表
    ll=list([5,6,8,None,None,10,None,None,9,None,7])
    #调用方法
    node=my.create_tree(input_list=ll)
    print('前序遍历')
    my.before_foreach(node)
    print('\n中序遍历')
    my.middle_foreach(node)
    print('\n后序遍历')
    my.after_foreach(node)

 

 2. 广度优先遍历

     广度优先遍历( Breadth First Search,BFS )也叫层序遍历,就是按照二叉树中的层次从左到右依次遍历每层中的结点。层序遍历的实现思路是利用队列来实现

     先将树的根结点入队,然后再让队列中的结点出队。队列中每一个结点出队的时候,都要将该结点的左子结点和右子结点入队。当队列中的所有结点都出队,树中的所有结点也就遍历完成。此时队列中结点的出队顺序就是层次遍历的最终结果。如下图所示:

 

(1) 根节点1入队列

 

(2) 节点1出队,输出节点1,并得到节点1的左孩子节点2、右孩子节点3。让节点2和节点3入队。

(3) 节点2出队,输出节点2,并得到节点2的左孩子节点4、右孩子节点5。让节点4和节点5入队。

(4) 节点3出队,输出节点3,并得到节点3的右孩子节点6。让节点6入队。

 

(5)节点4出队,输出节点4,由于节点4没有孩子节点,所以没有新节点入队。

(6)节点5出队,输出节点5,由于节点5同样没有孩子节点,所以没有新节点入队。

 

(7) 节点6出队,输出节点6,节点6没有孩子节点,没有新节点入队。

  使用递归的方式来操作,如上图所示

'''节点'''
class TreeNode:
    '''初始化数据'''
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

'''层序遍历'''
def level_order_traversal(root):
    # 判断节点为空
    if root is None:
        return []
    #数列
    result = []
    #队列
    queue = [root]
    #循环
    while queue:
        level = []  #层列
        #循环
        for _ in range(len(queue)):
            #第一个数据出队列
            node = queue.pop(0)
            #添加数据
            level.append(node.data)
            #判断左节点是否不为空
            if node.left is not None:
                queue.append(node.left)
            # 判断左节点是否不为空
            if node.right is not None:
                queue.append(node.right)
        #添加到列表中
        result.append(level)
    return result

if __name__ == '__main__':
    #二叉树对象
    root = TreeNode(1)
    root.left = TreeNode(2)
    root.right = TreeNode(3)
    root.left.left = TreeNode(4)
    root.left.right = TreeNode(5)
    root.right.right = TreeNode(6)

    print(level_order_traversal(root))

 

    在实际应用中,二叉树又是使用最广泛的,特别是二叉树的几种遍历操作的规则,需要重点掌握。在面试或应试中,通常会根据前序、中序、后序中的两种序列,询问另外一种树的遍历结果。

 

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

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

相关文章

公园高速公路景区校园IP网络广播音柱SIP音柱

公园高速公路景区校园IP网络广播音柱SIP音柱 适用于学校、车站、教堂、工厂、仓库、公园停车场及露天市场高速公路等场所播放录制语音文件或背景音乐节目,专业一体化音箱设计,高强度防水设计,符合IP54防护等认证,数字化产品&…

一个开源的全自动视频生成软件MoneyPrinterTurbo

只需提供一个视频 主题 或 关键词 ,就可以全自动生成视频文案、视频素材、视频字幕、视频背景音乐,然后合成一个高清的短视频。 一:功能特性 完整的 MVC架构,代码 结构清晰,易于维护,支持 API 和 Web界面…

用Scrapy抓取当当网站数据

setting.py实验目的及要求: 【实验目的】 通过本实验了解Scrapy爬虫框架;熟练掌握Scrapy的基本使用方法和常用技巧。 【实验要求】 使用Scrapy框架,抓取网站商品信息(京东、淘宝、当当等任选一个),并将结…

软考 系统架构设计师系列知识点之大数据设计理论与实践(8)

接前一篇文章:软考 系统架构设计师系列知识点之大数据设计理论与实践(7) 所属章节: 第19章. 大数据架构设计理论与实践 第3节 Lambda架构 19.3.3 Lambda架构介绍 1. 批处理层 2. 加速层 对加速层批处理视图建立索引&#xff0c…

如何将Oracle 中的部分不兼容对象迁移到 OceanBase

本文总结分析了 Oracle 迁移至 OceanBase 时,在出现三种不兼容对象的情况时的处理策略以及迁移前的预检方式,通过提前发现并处理这些问题,可以有效规避迁移过程中的报错风险。 作者:余振兴,爱可生 DBA 团队成员&#x…

【网络编程】如何创建一个自己的并发服务器?

hello !大家好呀! 欢迎大家来到我的网络编程系列之如何创建一个自己的并发服务器,在这篇文章中,你将会学习到在Linux内核中如何创建一个自己的并发服务器,并且我会给出源码进行剖析,以及手绘UML图来帮助大家…

基于Docker构建CI/CD工具链(十)总结

我们用九篇文章简单的介绍了使用Docker构建CICD工具链,希望对你的工作有所帮助。 基于Docker构建CI/CD工具链(一)构建基础工具镜像 基于Docker构建CI/CD工具链(二)快速搭建Gitlab代码库 基于Docker构建CI/CD工具链&…

【DM8】ODBC

官网下载ODBC https://www.unixodbc.org/ 上传到linux系统中 /mnt下 [rootstudy ~]#cd /mnt [rootstudy mnt]# tar -zxvf unixODBC-2.3.12.tar.gz [rootstudy mnt]# cd unixODBC-2.3.12/ [rootstudy unixODBC-2.3.12]# ./configure 注意:若是报以上错 则是gcc未安…

[计算机效率] 网站推荐:格式转换类

4.2 格式转换类 在日常办公和学习中,我们经常需要将不同格式的文件进行转换,特别是PDF文件,因其跨平台、易阅读的特性而备受青睐。然而,PDF文件的编辑和转换往往是一个棘手的问题。今天,我为大家推荐一系列优质的文件…

笔试题2 -- 字符串数组中指定字符串间的最短距离

字符串数组中指定字符串间的最短距离 文章目录 字符串数组中指定字符串间的最短距离题目还原解法一:暴力遍历 (HashVector法)解法二:算法改进 (双指针法)总结 题目链接: 数组中两个字符串的最小距离 – 牛客网 题目还原 给定一个字符串数组s…

速卖通、阿里国际站自养买家账号补单测评核心问题

补单在跨境电商中扮演着重要的角色,卖家们了解到补单可以快速增加产品的销量、评论数量,提升排名,从而打造爆款产品。产品的购买率和评价对于转化率和平台排名至关重要! 当排名不断提高,带来的流量也会增加&#xff0…

机器学习和深度学习--李宏毅(笔记与个人理解)Day17

Day 17Convolutional Neyral Network (CNN) 卷积神经网络一般都用在image 上面比较多一些,所以课程的例子大多数也都是image Image Classification the same size how about for pc? 这里对于tensor 张量这个概念,我还是比较奇怪,在我认为一…

java混淆的公司有哪些

一些提供 Java 混淆服务的公司包括: PreEmptive Solutions:PreEmptive Solutions 提供了一系列用于保护 Java 和 .NET 应用程序的工具,包括混淆、代码压缩、加密和漏洞检测等功能。 DexGuard:DexGuard 是 Guardsquare 公司推出的…

ubuntu磁盘文件损坏不能启动的修复方法

目录 1.错误现象2.解决 1.错误现象 今天早上启动虚拟机中的ubuntu发生如下错误,不能正常启动 2.解决 根据上面的提示可以运行以下命令修复: e2fsck /dev/sda1 #根据提示输入y reboot重启后ubuntu系统正常.

HR面试潜台词_弹性工作不强制考勤=做不完就要加班 扁平管理化=没有升职空间 原则上不鼓励加班=

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞…

【Leetcode每日一题】 递归 - 二叉树的所有路径(难度⭐)(59)

1. 题目解析 题目链接:257. 二叉树的所有路径 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 针对二叉树路径的求解问题,我们可以采用深度优先遍历(DFS)的策略来寻找所…

【LAMMPS学习】八、基础知识(3.3)使用分布式网格

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

筑牢个人信息安全防线,海云安受邀参加武汉“名家论坛”国家安全教育日专题讲座

近日,武汉“名家论坛”国家安全教育日专题讲座活动《“刷脸”有风险,如何保护我们的个人信息安全?》在武汉图书馆报告厅举办,海云安副总工程师李博士受邀参加本次活动。 活动以线下讲座、线上直播的形式,结合“普法讲座…

【数据结构1-基本概念和术语】

这里写自定义目录标题 0.数据,数据元素,数据项,数据对项,数据结构,逻辑结构,存储结构1.结构1.1逻辑结构1.2存储结构1.2.1 顺序结构1.2.2链式结构 1.3数据结构1.3.1基本数据类型1.3.2抽象数据类型1.3.2.1一个…

算法学习——LeetCode力扣补充篇9(912. 排序数组、21. 合并两个有序链表、33. 搜索旋转排序数组、103. 二叉树的锯齿形层序遍历)

算法学习——LeetCode力扣补充篇9 912. 排序数组 912. 排序数组 - 力扣(LeetCode) 描述 给你一个整数数组 nums,请你将该数组升序排列。 示例 示例 1: 输入:nums [5,2,3,1] 输出:[1,2,3,5] 示例 2&…