数据结构-非线性结构-树形结构:有序树 ---->二叉树【动态数据结构】

2024-09-02 03:18

本文主要是介绍数据结构-非线性结构-树形结构:有序树 ---->二叉树【动态数据结构】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)

在这里插入图片描述

一、二叉树的特性

  • 性质1: 在二叉树的第i层上至多有2(i-1)个结点(i>0)
  • 性质2: 深度为k的二叉树至多有2(k-1)个结点(k>0)
  • 性质3: 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
  • 性质4:具有n个结点的完全二叉树的深度必为 log2(n+1)
  • 性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i=1 时为根,除外)

二、二叉树的种类

1、完全二叉树

完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树,其中满二叉树的定义是所有叶节点都在最底层的完全二叉树。

在这里插入图片描述

2、满二叉树

满二叉树:除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树,每一层都挂满了节点。

在这里插入图片描述

3、平衡二叉树

平衡二叉树(AVL树):当且仅当任何节点的两棵子树的高度差不大于1的二叉树

在这里插入图片描述

4、搜索/排序二叉树

排序二叉树(二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树),排序二叉树包含空树。

排序二叉树(BST)的要求:

  1. 若左子树不空,则左子树上所有节点的值均小于它的根节点的值
  2. 若右子树不空,则右子树上所有节点的值均大于它的根节点的值
  3. 左、右子树也分别为二叉搜索/排序树
    在这里插入图片描述

5、二分搜索树、AVL树(平衡二叉树)、红黑树(准平衡二叉树) 性能对比

在这里插入图片描述

三、二叉树的存储

1、顺序存储

顺序存储:将数据结构存储在固定的数组中,虽然在遍历速度上有一定的优势,但因所占空间比较大,是非主流二叉树
存储方式.二叉树通常以链式存储。

在这里插入图片描述

2、链式存储

链式存储:由于对节点的个数无法掌握,常见树的存储表示都转换成二叉树进行处理,子节点个数最多为2。

在这里插入图片描述

四、二叉树-代码实现

class Node(object):"""二叉树节点"""def __init__(self, item):self.elem = itemself.lchild = Noneself.rchild = Noneclass BinaryTree(object):"""完全二叉树"""def __init__(self, node=None):self.root = nodedef add(self, item):"""添加节点"""if self.root is None:self.root = Node(item)return# 队列queue = [self.root]# 从尾部添加数据while True:# 从头部取出数据node = queue.pop(0)# 判断左节点是否为空if node.lchild is None:node.lchild = Node(item)returnelse:queue.append(node.lchild)if node.rchild is None:node.rchild = Node(item)returnelse:queue.append(node.rchild)

五、二叉树的遍历

树的遍历:是树的一种重要的运算。所谓遍历是指对树中所有结点的信息的访问,即依次对树中每个结点访问一次且仅访问一次,我们把这种对所有节点的访问称为遍历(traversal)。

树的两种重要的遍历模式是:深度优先遍历广度优先遍历。深度优先一般用递归,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。

1、广度优先遍历

广度优先遍历:从树的root开始,从上到下从从左到右遍历整个树的节点

2、深度优先遍历

深度优先搜索(Depth First Search):对于一颗二叉树,深度优先搜索(Depth First Search)是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。深度遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。

三种深度优先遍历方式:

  • 先序遍历(preorder):根 左 右
  • 中序遍历(inorder):左 根 右
  • 后序遍历(postorder):左 右 根
    在这里插入图片描述
    在这里插入图片描述
    根据深度遍历结果反推二叉树的结构:由中序遍历&先序遍历 或者 中序遍历&后序遍历 的遍历结果就可以推出二叉树的结构
    在这里插入图片描述

3、二叉树遍历的代码实现

class Node(object):"""节点类"""def  __init__(self, item):self.item = itemself.lchild = Noneself.rchild = Noneclass BinaryTree(object):"""完全二叉树"""def __init__(self, node=None):self.root = nodedef add(self, item):"""添加节点"""if self.root == None:self.root = Node(item)return# 队列queue = []# 从尾部添加数据queue.append(self.root)while True:# 从头部取出数据node = queue.pop(0)# 判断左节点是否为空if node.lchild == None:node.lchild = Node(item)returnelse:queue.append(node.lchild)if node.rchild == None:node.rchild = Node(item)returnelse:queue.append(node.rchild)def breadh_travel(self):"""广度优先遍历"""if self.root == None:return# 队列queue = []# 添加数据queue.append(self.root)while len(queue)>0:# 取出数据node = queue.pop(0)print(node.item, end="")# 判断左右子节点是否为空if node.lchild is not None:queue.append(node.lchild)if node.rchild is not None:queue.append(node.rchild)def preorder_travel(self, root):"""先序遍历 根 左 右"""if root is not None:print(root.item, end="")self.preorder_travel(root.lchild)self.preorder_travel(root.rchild)def inorder_travel(self, root):"""中序遍历 左 根 右"""if root is not None:self.inorder_travel(root.lchild)print(root.item, end="")self.inorder_travel(root.rchild)def postorder_travel(self, root):"""后序遍历 根 左 右"""if root is not None:self.postorder_travel(root.lchild)self.postorder_travel(root.rchild)print(root.item, end="")if __name__ == '__main__':tree = BinaryTree()tree.add("0")tree.add("1")tree.add("2")tree.add("3")tree.add("4")tree.add("5")tree.add("6")tree.add("7")tree.add("8")tree.add("9")tree.preorder_travel(tree.root)print()tree.inorder_travel(tree.root)print()tree.postorder_travel(tree.root)

这篇关于数据结构-非线性结构-树形结构:有序树 ---->二叉树【动态数据结构】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1128844

相关文章

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

redis数据结构之String详解

《redis数据结构之String详解》Redis以String为基础类型,因C字符串效率低、非二进制安全等问题,采用SDS动态字符串实现高效存储,通过RedisObject封装,支持多种编码方式(如... 目录一、为什么Redis选String作为基础类型?二、SDS底层数据结构三、RedisObject

Java集合中的链表与结构详解

《Java集合中的链表与结构详解》链表是一种物理存储结构上非连续的存储结构,数据元素的逻辑顺序的通过链表中的引用链接次序实现,文章对比ArrayList与LinkedList的结构差异,详细讲解了链表... 目录一、链表概念与结构二、当向单链表的实现2.1 准备工作2.2 初始化链表2.3 打印数据、链表长

创建springBoot模块没有目录结构的解决方案

《创建springBoot模块没有目录结构的解决方案》2023版IntelliJIDEA创建模块时可能出现目录结构识别错误,导致文件显示异常,解决方法为选择模块后点击确认,重新校准项目结构设置,确保源... 目录创建spChina编程ringBoot模块没有目录结构解决方案总结创建springBoot模块没有目录

SpringBoot利用树形结构优化查询速度

《SpringBoot利用树形结构优化查询速度》这篇文章主要为大家详细介绍了SpringBoot利用树形结构优化查询速度,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一个真实的性能灾难传统方案为什么这么慢N+1查询灾难性能测试数据对比核心解决方案:一次查询 + O(n)算法解决

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-