025.【树形结构算法】

news2024/10/6 16:25:35

1. 树的定义

树形结构是由n个元素组成的有限集合,如果n=0,那么就称为空树;如果n>0,树形结构应该满足以下条件:

  • 有一个特定的结点,称为根结点或根。

  • 除根结点外,其余结点被分成m(m≥0)个互不相交的有限集合,而每个子集又都是一棵树(称为原树的子树)。

在这里插入图片描述

在介绍树形结构的条件时,提到了一个特殊的结点(根)。所示的树形结构的根就是结点a,就像树一样,树木要想长出茂密的枝条和叶子,就离不开树根。树形结构的形成也离不开根结点,只不过树是向上生长,而树形结构是从根往下描绘。根结点上面再也没有结点。

除了a这个根结点,图中的树形结构还有结点b,c,d,e,f,g,它们的共同点是不论是结点上面还是结点下面,至少都会存在1个与之连接的结点。并且为了能够结束树形结构,必须保证有一些无后续的结点,结点b,d,f,g。否则,就会变成一个无限的树形结构。

  • 结点:“蓝色球”就被称为结点。

  • 子树:以某个结点的子结点为根构成的树,称为该结点的子树。a结点它的子结点是c,以c为根构成的树,称为结点a的子树。类似于生活中的树的分叉上的树枝和叶子。

  • 分支:各结点之间的关系,类似于生活中的树枝。

  • :结点拥有的子树的个数称为该结点的度。结点a它的下一层(后继)有b,c,d这3个结点,因此结点a的度是3。

  • 父结点:每个结点的上一层(前驱)结点,结点e它的父结点是c,结点c的父结点是a。

  • 根结点:没有上一层(前驱)结点,一个树形结构只有一个根结点,结点a就是根结点。

  • 子结点:某个结点的下一层(后继)结点,结点e,f 就是结点c的子结点。

  • 叶子结点:没有下一层(后继)结点,称为叶子结点。叶子结点的度是0。结点b,g,f,g,就是叶子结点。

  • 树的度:树中所有结点最大的度,称为树的度。a的度是3,c的度是2,e的度是1,最大的度是3,因此整个树形结构的度是3。

  • 层次(层号):树中所有结点的度之和再加1。图所示的层次为:3×1+2×1+1×1+1=7,因此这个树形结构的层次是7

  • 兄弟结点:拥有同一个父结点的结点称为兄弟结点。b、c、d就是兄弟结点。

  • 深度:树中结点所处的最大层次,称为树的深度。树形结构一共有4层,它的深度就是4。

  • 森林:互补相交的树的集合称为森林。类似于生活中很多大树便构成森林

2. 什么是二叉树

二叉树依然是树形结构。但是二叉树还有一个条件:它的每个结点都有两个分支,左侧分支称为“左子树”;右侧分支称为“右子树”,因此二叉树的最大的度就是2。

在这里插入图片描述
二叉树有如下几个基本特性:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 二叉树操作

二叉树和其他数据结构一样,需要存储在内存中,二叉树存储有两种方式,一种是用数组方式存储,另一种是用链表方式存储。

在这里插入图片描述
设计一个程序,用户输入数组内容,运行程序之后,按照“满二叉树”输出内容。具体代码如下:

"""
功能:用数组创建二叉树
参数:tree_array:存放二叉树数组
      data:数据
      length:长度
"""
def Binary_tree_create(tree_array, data, length):
    for i in range(1, length):
        index = 1                               	# 索引值初始化
        while tree_array[index] != 0:
            if data[i] > tree_array[index]: 		# 如果数组内的值大于树根,则往右子树比较
                index = index * 2 + 1
            else:                             		# 如果数组内的值小于或等于树根,则往左子树比较
                index = index * 2
        tree_array[index] = data[i]         		# 把数组值放入二叉树

length = 9                                      	# 长度为9
data = [0,3,2,6,7,4,5,1,9]                        	# 原始数组
tree_array = [0] * 16                              	# 存放二叉树数组

print('原始数组内容:')
for i in range(length):
    print('%2d ' % data[i], end='')

print('')
Binary_tree_create(tree_array, data, 9)

print('二叉树内容:')
for i in range(1, 16):
    print('%2d ' % tree_array[i], end='')
print()

将0去掉之后,就是这个程序要实现的二叉树。
在这里插入图片描述在这里插入图片描述
用数组实现二叉树的优点是:对于任意结点都很容易找到父结点、子结点和兄弟结点。如果是斜二叉树,该方法可能会占用大量空间,造成空间浪费。因此对于结点分布不均匀的二叉树来说,则用数组实现二叉树的方式会使效率降低,而且在删除和插入结点时,也不方便操作。在实际应用中,一般还是用链表来实现这样的二叉树。

在这里插入图片描述
用Python代码实现链表式二叉树结点的代码如下:

class tree:
    def __init__(self):
        self.data=0                       # 数据域
        self.left=None                     # 左子结点指针
        self.right=None                  # 右子结点指针

用链表方式建立二叉树的Python算法如下:

"""
功能:创建二叉树
参数:root:表示根结点
      value:保存的值
"""
def creat_tree(root,value):
	new_node=tree()                                	# 创建树结点
    new_node.data=value                         	# 数据域
    new_node.left=None                         		# 左子树
    new_node.right = None                        	# 右子树
    if root==None:                              	# 如果根结点是空,这种情况就是空二叉树
        root=new_node                         		# 直接将根结点给新树
        return root                              	# 返回根结点
    else:
        current=root                             	# 当前结点
        while current!=None:
            backup=current
            if current.data>value:                  # 大于保存数值
                current=current.left               	# 放在左子树
            else:                                	# 否则
                current=current.right              	# 放在右子树
        if backup.data>value:
            backup.left=new_nod               		# 将数据左子树放在新树中
        else:
            backup.right=new_node              		# 将数据右子树放在新树中
    return root

在这里插入图片描述
可以使用递归算法来实现上述步骤,因此使用Python代码实现前序遍历的算法如下:

def preorder(self,tree):           		# 前序遍历,tree是树结点
    if tree == None:          			# 判断是空子树
        return
    # 当不为空子树时,先打印根结点,再打印左结点,最后打印右结点
    print(tree.data)
    self.preorder(tree.left)
    self.preorder(tree.right)

在这里插入图片描述
可以使用递归算法来实现上述步骤,因此使用Python代码实现中序遍历的算法如下:

def inorder(self,tree):             		# 中序遍历,tree是树结点
    if tree == None:          				# 判断是空子树
        return
    # 当不为空子树时,先打印左结点,再打印根结点,后打印右结点
    self.inorder(tree.left)
    print(tree.data)
    self.inorder(tree.right)

在这里插入图片描述
可以使用递归算法来实现上述步骤,因此使用Python代码实现后序遍历的算法如下:

def postorder(self,tree):             		# 后序遍历,tree是树结点
    if tree == None:             			# 判断是空子树
        return
    # 当不为空子树时,先打印左结点,再打印右结点,后打印根结点
    self.postorder(tree.left)
    self.postorder(tree.right)
    print(tree.data)

先创建一个二叉树,即结点内容用a,x,c,t,b,f,y,z来表示,分别用先序遍历、中序遍历、后序遍历,按顺序输出此二叉树各个结点。具体代码如下:

class tree(object):                                    			# 创建树结点

    def __init__(self, data=None, left=None, right=None):     	# 结点位置
        self.data = data                                     	# 数据域
        self.left = left                                    	# 左子树
        self.right = right                                  	# 右子树

class BinaryTree(object):                                   	# 创建二叉树

    def __init__(self, root=None):                              # 初始化
        self.root = root

    def is_empty(self):                                   		# 判断是否为空
        return self.root == None

    def preorder(self,tree):                                  	# 前序遍历
        if tree == None:                                 		# 判断是空子树
            return
        # 当不为空子树时,先打印根结点,再打印左结点,后打印右结点
        print(tree.data)
        self.preorder(tree.left)
        self.preorder(tree.right)

    def inorder(self,tree):                                  	# 中序遍历
        if tree == None:                                 		# 判断是空子树
            return
        # 当不为空子树时,先打印左结点,再打印根结点,后打印右结点
        self.inorder(tree.left)
        print(tree.data)
        self.inorder(tree.right)

    def postorder(self,tree):                                 	# 后序遍历
        if tree == None:                                 		# 判断是空子树
            return
             # 当不为空子树时,先打印左结点,再打印右结点,后打印根结点
        self.postorder(tree.left)
        self.postorder(tree.right)
        print(tree.data)

 

n1 = tree(data="z")                                          		# 二叉树结点z
n2 = tree(data="y")                                           		# 二叉树结点y
n3 = tree(data="f")                                          		# 二叉树结点f
n4 = tree(data="b", left=n1, right=None)                           	# 二叉树结点b,左子树为z,无右子树
n5 = tree(data="t", left=None, right=n4)                            # 二叉树结点t,无左子树为,右子树为b
n6 = tree(data="c", left=None, right=n2)                         	# 二叉树结点c,无左子树为,右子树为y
n7 = tree(data="x", left=n6, right=n3)                             	# 二叉树结点x,左子树为c,右子树为f
root = tree(data="a", left=n5, right=n7)                            # 根结点a,左子树为t,右子树为x

ct = BinaryTree(root)                                       		# 创建二叉树
print('先序遍历')
ct.preorder(ct.root)                                        		# 输出前序遍历二叉树结果
print('中序遍历')
ct.inorder(ct.root)                                        			# 输出中序遍历二叉树结果
print('后序遍历')
ct.postorder(ct.root)                                      			# 输出后序遍历二叉树结果

二叉树在建立过程中,是根据“左子树<树根<右子树”的原则建立的,因此只需从根结点开始比较键值就可以。如果键值比树根大就向右子树查找,如果键值比树根小就向左子树查找,直到键值相等就找到要查找的值。

用Python代码实现的二叉树查找算法如下:

def search(p,val):                    	# 查找二叉树中某个值
    while True:                    		# 循环查找
        if p==None:              		# 没找到就返回None
            return None
        if p.data==val:         		# 查找值等于结点值
            return p
        elif  val<p.data :       		# 查找值小于结点值
            ptr=p.left        			# 向左子树查找
        else:                         	# 否则
            ptr=p.right       			# 向右子树查找

在这里插入图片描述
查找二叉树的数据,具体代码如下:

class tree:

    def __init__(self):
        self.data=0                         	# 数据域
        self.left=None                        	# 左子结点指针
        self.right=None                       	# 右子结点指针

"""
功能:创建二叉树
参数:root:表示根结点
      value:保存的值
"""
def creat_tree(root,value):
    new_node=tree()                          	# 创建树结点
    new_node.data=value                        	# 数据域
    new_node.left=None                        	# 左子树
    new_node.right = None                      	# 右子树
    if root==None:                              # 如果根结点是空,这种情况就是空二叉树
        root=new_node                         	# 直接将根结点给新树
        return root                          	# 返回根结点
    else:
        current=root                            # 当前结点
        while current!=None:
            backup=current
            if current.data>value:          	# 大于保存数值
                current=current.left            # 放在左子树
            else:                               # 否则
                current=current.right           # 放在右子树
        if backup.data>value:
            backup.left=new_node             	# 将数据左子树放在新树中
        else:
            backup.right=new_node               # 将数据右子树放在新树中
    return root

def search(p,val):                             	# 查找二叉树中的某个值

    i=1
    while True:                              	# 循环查找
        if p==None:                          	# 没找到就返回None
            return None
        if p.data==val:                        	# 查找值等于结点值
            print("共计查找 ",i,"次")
            return p
        elif  val<p.data :                     	# 查找值小于结点值
            p=p.left                         	# 向左子树查找
        else:                               	# 否则
            p=p.right                        	# 向右子树查找
        i+=1                              		# 查找次数加1

arr=[6,3,8,2,5,1,7]
p=None
print('数据内容是')
for i in range(7):
    p=creat_tree(p,arr[i])                     	# 建立二叉树
    print('%2d ' %arr[i],end='')
print()
data=int(input('请输入查找值:'))
if search(p,data) !=None :                    	# 在二叉树中查找
    print("您要找的值",data,"找到了^_^" )
else:
    print("您要找的值没找到^ ^")

二叉树结点插入的情况和查找类似,如果要插入的结点已经在二叉树中,就不必插入了;如果要插入的结点不在二叉树中,就利用创建函数将数据插入到二叉树中,插入之后的二叉树依然保持左子树比根结点小,右子树比根结点大的特性。

利用Python代码实现二叉树结点的插入算法如下:

if search(ptr,data)!=None:                          				# 在二叉树中查找
    print("真巧,二叉树中已经有你输入的结点啦~")
else:                                                             	# 不在二叉树中
    ptr=creat_tree(ptr,data)                       					# 调用创建函数将数据插入
    inorder(ptr)                              						# 输出插入之后的新的二叉树

给定一个二叉树内容为6,3,8,2,5,1,7,用户输入一个想要在此二叉树中插入的键值。成功插入后,最终用中序遍历输出此二叉树各个结点内容。具体代码如下:

class tree:
    def __init__(self):
        self.data=0                       		# 数据域
        self.left=None                     		# 左子结点指针
        self.right=None                    		# 右子结点指针

"""
功能:创建二叉树
参数:root:表示根结点
      value:保存的值
"""
def creat_tree(root,value):
    new_node=tree()                      		# 创建树结点
    new_node.data=value                  		# 数据域
    new_node.left=None                    		# 左子树
    new_node.right = None                  		# 右子树
    if root==None:                        		# 如果根结点是空,这种情况就是空二叉树
        root=new_node                   		# 直接将根结点给新树
        return root                        		# 返回根结点
    else:
        current=root                      		# 当前结点
        while current!=None:
            backup=current
            if current.data>value:             	# 大于保存数值
                current=current.left         	# 放在左子树
            else:                           	# 否则
                current=current.right        	# 放在右子树
        if backup.data>value:
            backup.left=new_node           		# 将数据左子树放在新树中
        else:
            backup.right=new_node          		# 将数据右子树放在新树中
    return root

def search(p,val):                          	# 查找二叉树中某个值
    while True:                                 # 循环查找
        if p==None:                             # 没找到就返回None
            return None
        if p.data==val:                         # 查找值等于结点值
            return p
        elif  val<p.data :                      # 查找值小于结点值
            p=p.left                           	# 向左子树查找
        else:                                 	# 否则
            p=p.right                         	# 向右子树查找

def inorder(ptr):                              	# 中序遍历子程序
    if ptr!=None:
        inorder(ptr.left)
        print('%2d ' %ptr.data, end='')
        inorder(ptr.right)

arr=[6,3,8,2,5,1,7]
ptr=None
print("数据内容是:")

for i in range(7):
    ptr=creat_tree(ptr,arr[i])                  # 建立二叉树
    print('%2d ' %arr[i],end='')
print()
data=int(input('请输入要插入的键值:'))

if search(ptr,data)!=None:                      # 在二叉树中查找
    print('真巧,二叉树中已经有你输入的结点啦~')
else:
    print("插入数据后中序遍历输出结果为:")
    ptr=creat_tree(ptr,data)                   	# 将数据插入树中
    inorder(ptr)                               	# 中序遍历输出各数据

插入数据4之后的二叉树如图所示。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

面试官:一个 TCP 连接可以发多少个 HTTP 请求?

目录 &#x1f914; 第一个问题 &#x1f914; 第二个问题 &#x1f914; 第三个问题 &#x1f914; 第四个问题 &#x1f914; 第五个问题 曾经有这么一道经典面试题&#xff1a;从 URL 在浏览器被被输入到页面展现的过程中发生了什么&#xff1f; 相信大多数准备过的同…

产品经理面试常见的25个必问题(一)

1、你认为产品经理的工作职责是什么&#xff1f; ●需求阶段&#xff08;需求收集、需求管理、需求分析、需求评估&#xff09; ●设计阶段&#xff08;业务流程、功能模块、原型交互、需求文档&#xff09; ●开发阶段&#xff08;需求评审、项目管理、测试验收&#xff09…

centos版本的EDA虚拟机搭建1

0、参考博客 Centos镜像国内最全下载地址 VMware Workstation CPU如何设置才更加合理&#xff1f;如何才能发挥虚拟机最大性能 1、下载网站 http://mirrors.aliyun.com/centos/7/isos/x86_64/centos镜像文件下载完成。 2、vmware搭建centos 新建虚拟机。 选择自定义。 …

mysql中的索引

1、索引是什么&#xff1f; 在mysql当中&#xff0c; 内部系统它有两种查询方式&#xff0c; 一种是(全盘扫描查询)&#xff0c;另外一种是通过(索引检索查询)&#xff0c;通过添加了索引的字段进行查询&#xff0c; 可以大大提高查询效率 mysql中的索引相当于一本书中的目录&a…

java 物流配货管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 物流配货管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

centos7系统:HAProxy软件部署

目录 目 的&#xff1a; 硬件需求: ​编辑 实验环境配置&#xff1a; haproxy的服务器配置&#xff1a; nfsrps服务器部署&#xff1a; nginx服务器1部署: nginx服务器2部署&#xff1a; 目 的&#xff1a; 两台nginx服务器做web服务&#xff0c;haproxy服务器做调度负载均…

(6.9-6.15)【大数据新闻速递】

【上海数交所将携手清华大学等举办首届数据资产入表研修班】 上海数据交易所获悉&#xff0c;数交所将联合清华大学五道口金融学院、上海市数商协会于6月28日至29日举办首届数据资产入表研修班。财政部印发《企业数据资源相关会计处理暂行规定&#xff08;征求意见稿&#xff…

前沿应用丨大规模无人机集群与“虚实结合”半实物仿真系统

一、应用背景 无人机集群在军事、安全、救援、航空监测、物流配送等领域具有广泛的应用前景。它可以提高任务执行的效率、灵活性和安全性&#xff0c;同时降低人力资源的需求和风险&#xff0c;无人机集群研究涉及多个学科领域&#xff0c;如机器人学、控制理论、通信技术和人工…

【算法与数据结构】383、LeetCode赎金信

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题的思路和242、有效的字母异位词的思路一样   程序如下&#xff1a; class Solution { public…

好好存钱,是成年人最顶级的自律

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 王尔德说&#xff1a;“在我年轻的时候&#xff0c;曾以为金钱是世界上最重要的东西。现在我老了&#xff0c;才知道的确如此。” 路遥说&#xff1a;“钱是好东西&#xff0c;它能使人不再心慌&#…

指纹识别工具WhatWeb使用教程,图文教程(超详细)

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 WhatWeb 一、扫描网站指纹二、扫描强度三、扫描内网…

ZeroQuant-V2 LLM权重与激活量化

ref ZeroQuant-V2: Exploring Post-training Quantization in LLMs from Comprehensive Study to Low Rank Compensation 4bit量化为什么重要 The case for 4-bit precision: k-bit Inference Scaling Laws 这篇文章研究表明4bit通常是最优的量化方法&#xff1a;同样的量化…

快速选择合适的GNSS模拟器,看这几个重点

为了正确测试GNSS接收器或其他任何依赖GNSS信号的系统或设备&#xff0c;工程师需要模拟与真实卫星广播相同的RF信号&#xff0c;而使用GNSS模拟器是实现这一工作的最佳选择。 假设正在开发一种需要集成GNSS接收器的新产品&#xff0c;想要验证接收器设备在不同条件下是否运行…

企业为什么要关注库存?因为那都是“钱”!

库存是企业管理的核心&#xff0c;公司必须提供足够的商品来满足客户需求&#xff0c;但又不能冒着浪费金钱和资源的风险&#xff0c;一味的增加库存。 不同的企业在库存管理这个问题上就“八仙过海各显神通”了&#xff0c;常见的处理方法有&#xff1a; 1. 经验法&#xff1a…

求两数之和

必应壁纸供图 题目描述 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不…

基于SpringBoot+Vue的学生毕业离校系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

Sui x KuCoin Labs夏季黑客松首批入围项目公布

经过一段时间的共同努力&#xff0c;我们已经完成了对Sui x KuCoin Labs夏季黑客松第一批入围项目的审核&#xff0c;并宣布以下团队已入围最终demo day&#xff1a; 首批入围名单 Desig Protocol Desig协议提供了一种与区块链无关&#xff08;无智能合约&#xff09;的多重…

聚观早报|奔驰接入ChatGPT聊天机器人;极兔速递提交上市申请书

今日要闻&#xff1a;奔驰接入ChatGPT聊天机器人&#xff1b;极兔速递向港交所提交上市申请书&#xff1b;微软股价创历史新高&#xff1b;美电动卡车Nikola宣布裁员23%&#xff1b;马斯克&#xff1a;人工智能具有颠覆性 奔驰接入ChatGPT聊天机器人 梅赛德斯 - 奔驰表示&…

Doris 扩缩容和副本均衡

扩缩容和副本均衡 ​ 对于集群节点发生变化&#xff08;扩缩容&#xff09;时&#xff0c;集群内部的tablet是如何以一定的策略完成数据的重分布&#xff0c;从而达到每个be能够分布尽可能数量相同的tablet。同时&#xff0c;集群内部某些tablet由于某些原因发生损坏时&#x…

快手web验证日志分析

文章目录 log参数session_ididentityproject_id 流程1-4请求参数sign日志formdata828586 log参数 为了确定日志中是否有参数和IP绑定&#xff0c;检查了session_id参数。 session_id session_id i (wn[e[t 0]] wn[e[t 1]] wn[e[t 2]] wn[e[t 3]] "-" wn…