目录

二叉树数据结构

简介

为何选择树

树的主要应用包括:

二叉树的类型

满二叉树(Full binary tree)

完全二叉树(Complete binary tree)

完美二叉树(Perfect binary tree)

平衡二叉树(Balanced Binary Tree)

退化(或病态)树(Degenerate (or pathological) tree)

二叉排序树

代码实现

以class类创建树的单个节点

创建一个简单的树

创建二叉排序树(递归插入方法)

树遍历(前序,中序和后序)

前序遍历

中序遍历

后序遍历

删除树


二叉树数据结构

简介

元素最多包含2个子元素的树称为二叉树。由于二叉树中的每个元素只能有2个子元素,因此我们通常将它们命名为左右子元素。

二叉树节点包含以下部分。

  1. 数据
  2. 指向左子节点的指针
  3. 指向右子节点的指针

树:与阵列,链接列表,堆栈和队列(线性数据结构)不同,树是分层数据结构。

树 词汇表:最顶层的节点称为树的根。直接位于元素下的元素称为子元素。直接在某个东西上方的元素称为其父元素。例如,'a'是'f'的子元素,'f'是'a'的父元素。最后,没有孩子的元素被称为叶子。

      tree----j    <-- root/   \f      k  /   \      \a     h      z    <-- leaves 

为何选择树

1. 使用树的一个原因可能是因为您希望存储自然形成层次结构的信息。例如,计算机上的文件系统:

file system
-----------/    <-- root/      \
...       home/          \ugrad        course/       /      |     \...      cs101  cs112  cs113  

2.树(具有一些排序,例如BST)提供适度的访问/搜索(比链接列表更快并且比数组慢)。
3.树提供适度的插入/删除(比阵列更快,比无序链接列表慢)。
4.与链接列表类似,与阵列不同,当节点使用指针链接时,树没有节点数量的上限。

树的主要应用包括:

1. 处理分层数据。
2. 使信息易于搜索(参见树遍历)。
3. 处理已排序的数据列表。
4. 作为合成视觉效果的数字图像的工作流程。
5. 路由器算法
6. 多阶段决策的形式(见商业象棋)。

二叉树的类型

满二叉树(Full binary tree)

如果每个节点有0或2个子节点,则二叉树已满。

以下是满二叉树的示例。我们还可以说满二叉树是一个其中除了叶子之外的所有节点都有两个子节点的二叉树。

               18/       \  15         30  /  \        /  \ 40    50    100   40 18/    \   15     20    /  \       40    50   /   \30   5018/     \  40       30  /  \100   40

在满二叉树文件中,叶节点数是内部节点数加1,内部节点是有子节点的的节点
       L = I + 1
其中L =叶节点数,I =内部节点数

完全二叉树(Complete binary tree)

完全二叉树,所有层都被完全填充,除了可能是最后一级,最后一级是尽可能保留所有键

以下是完整二叉树的示例

               18/       \  15         30  /  \        /  \40    50    100   4018/       \  15         30  /  \        /  \40    50    100   40/  \   /8   7  9 

完美二叉树(Perfect binary tree)

二叉树是完美的二叉树,其中所有内部节点都有两个子节点,所有叶子都在同一级别。
以下是完美二叉树的例子

              18/       \  15         30  /  \        /  \40    50    100   4018/       \  15         30  

高度为h的完美二叉树(其中高度是从根到叶的路径上的节点数)具有2^(h - 1)个节点。

平衡二叉树(Balanced Binary Tree

如果树的高度为O(Log n),则二叉树是平衡的,其中n是节点数。例如,AVL树通过确保左右子树高度之间的差异最大为1来维持O(Log n)高度。红黑树通过确保黑色节点的数量保持O(Log n)高度每个根到叶子路径是相同的,没有相邻的红色节点。平衡二进制搜索树在性能方面是明智的,因为它们为搜索,插入和删除提供了O(log n)时间。

退化(或病态)树(Degenerate (or pathological) tree

每个内部节点都有一个子树。这些树在性能方面与链表相同。

      10/20\30\40     

二叉排序树

二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

(1)若左子树不空,则左子树上所有节点的值均小于它的根节点的值;

(2)若右子树不空,则右子树上所有节点的值均大于它的根节点的值;

(3)左、右子树也分别为二叉排序树;

(4)没有键值相等的节点。

代码实现

以class类创建树的单个节点

使用python的class类表示单个节点,节点中应包含当前节点的值、左节点指针、右节点指针

class Node:def __init__(self, data=None):self.val = data    # 节点值指针self.right = None  # 右节点指针self.left = None   # 左节点指针

创建一个简单的树

先创建跟节点,然后依次分配左右子节点

if __name__ == '__main__':tree = Node(1)''' 以下是上述声明后的树 1 /   \ None  None'''tree.left = Node(2)tree.right = Node(3)''' 2和3成为1的左右子树1 /   \ 2      3 /    \    /  \ None None None None'''tree.left.left = Node(4)''' 4成为2的左子树1 /       \ 2          3 /   \       /  \ 4    None  None  None /  \ None None'''

创建二叉排序树(递归插入方法)

步骤:

1、若根结点的值等于查找的值,成功。

2、否则,若小于根结点的值,递归查左子树。

3、若大于根结点的值,递归查右子树。

4、若子树为空,查找不成功。

class Node:def __init__(self, data=None):self.value = data    # 节点值指针self.right = None    # 右节点指针self.left = None     # 左节点指针def insert(self, data):if self.value:                       # 判断是否存在根节点if data < self.value:            # 若小于当前根节点,则放左边if self.left is None:        # 若左边子树是空的,则添加到后面self.left = Node(data)   # 新建节点后添加入末尾else:                        # 否则递归调用,直到到达末尾self.left.insert(data)elif data > self.value:          # 若大于当前跟节点,则放右边if self.right is None:       # 若右边子树是空的,则添加到后面self.right = Node(data)  # 新建节点后添加入末尾else:                        # 否则递归调用,直到到达末尾self.right.insert(data)else:self.value = data                # 不存在根节点,就将值设置为根节点

树遍历(前序,中序和后序)

前序遍历

算法(树)1.访问root。2.遍历左子树,即调用Preorder(左子树)3.遍历右子树,即调用Preorder(右子树)

ABDHIEJCFKG
class Node:def preorderTraversal(self, root):res = []if root:res.append(root.value)res += self.preorderTraversal(root.left)res += self.preorderTraversal(root.right)return resif __name__ == '__main__':tree = Node()tree.insert(2)tree.insert(3)tree.insert(5)tree.insert(1)tree.insert(7)res = tree.preorderTraversal(tree)print(res)# Output:
# [2, 1, 3, 5, 7]

中序遍历

算法顺序(树)
1.遍历左子树,即调用Inorder(左子树)
2.访问root。
3.遍历右子树,即调用Inorder(右子树)

HDIBEJAFKCG
class Node:def inorderTraversal(self, root):res = []if root:res += self.inorderTraversal(root.left)res.append(root.value)res += self.inorderTraversal(root.right)return resif __name__ == '__main__':tree = Node()tree.insert(2)tree.insert(3)tree.insert(5)tree.insert(1)tree.insert(7)res = tree.inorderTraversal(tree)print(res)# Output:
# [1, 2, 3, 5, 7]

后序遍历

算法(树)1.遍历左子树,即调用Postorder(左子树)2.遍历右子树,即调用Postorder(右子树)3.访问root。

HIDJEBKFGCA
class Node:def postorderTraversal(self, root):res = []if root:res += self.postorderTraversal(root.left)res += self.postorderTraversal(root.right)res.append(root.value)return resif __name__ == '__main__':tree = Node()tree.insert(2)tree.insert(3)tree.insert(5)tree.insert(1)tree.insert(7)res = tree.postorderTraversal(tree)print(res)# Output:
# [1, 7, 5, 3, 2]

删除树

要删除树,我们必须遍历树的所有节点并逐个删除它们。所以我们应该使用哪种遍历? - 前序或中序或后序?答案很简单 -> 后序,因为在删除父节点之前,我们应该首先删除它的子节点。删除了树,还要将root更改为NULL

对于以下树节点,按顺序删除 - 4,5,2,3,1

def _deleteTree(root):if root:_deleteTree(root.left)          # 首先删除两个子树_deleteTree(root.right)         # 首先删除两个子树print(" 删除节点:", root.value)root = None                     # 然后删除节点def deleteTree(root):_deleteTree(root)   # 删除树root = None         # 并将根设置为NULLif __name__ == '__main__':tree = Node()tree.insert(2)tree.insert(3)tree.insert(5)tree.insert(1)tree.insert(7)res = tree.postorderTraversal(tree)print(res)deleteTree(tree)# Output:
# [1, 7, 5, 3, 2]
# 删除节点: 1
# 删除节点: 7
# 删除节点: 5
# 删除节点: 3
# 删除节点: 2

未完待续...

欢迎关注↓↓↓

  • 头条号:小锋学长

  • 微信公众号:xfxuezhang

Python二叉树详解笔记相关推荐

  1. python算法详解 张玲玲_Python算法详解

    目 录 第 1章 算法概述 1 1.1 算法的基础 2 1.1.1 算法的特征 2 1.1.2 何为算法 2 1.2 计算机中的算法 3 1.2.1 认识计算机中的算法 3 1.2.2 为什么说算法是 ...

  2. 一周刷爆LeetCode,算法da神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记

    一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解 笔记 教程与代码地址 P1 出圈了!讲课之外我们来聊聊 ...

  3. Mask_RCNN翻译和详解笔记一(原文翻译+源代码+代码使用说明)

    Mask_RCNN翻译和详解笔记一(原文翻译+源代码+代码使用说明) 2018年06月01日 23:45:47 阅读数:332 原文:https://github.com/matterport/Mas ...

  4. python区块链开发_Fabric区块链Python开发详解

    Hyperledger Fabric是最流行的联盟区块链平台.Fabric区块链Python开发详解课程 涵盖Fabric区块链的核心概念.Fabric网络搭建.Node链码开发.Python应用开发 ...

  5. python装饰器setter_第7.27节 Python案例详解: @property装饰器定义属性访问方法getter、setter、deleter...

    上节详细介绍了利用@property装饰器定义属性的语法,本节通过具体案例来进一步说明. 一.    案例说明 本节的案例是定义Rectangle(长方形)类,为了说明问题,除构造函数外,其他方法都只 ...

  6. 【python】详解类class的继承、__init__初始化、super方法

    原文链接; https://blog.csdn.net/brucewong0516/article/details/79121179?utm_medium=distribute.pc_relevant ...

  7. python与golang_Golang与python线程详解及简单实例

    Golang与python线程详解及简单实例 在GO中,开启15个线程,每个线程把全局变量遍历增加100000次,因此预测结果是 15*100000=1500000. var sum int var ...

  8. python 最小二乘法_最小二乘法及其python实现详解

    最小二乘法Least Square Method,做为分类回归算法的基础,有着悠久的历史(由马里·勒让德于1806年提出).它通过最小化误差的平方和寻找数据的最佳函数匹配.利用最小二乘法可以简便地求得 ...

  9. 【python】详解multiprocessing多进程-Pool进程池模块(二)

    [python]详解multiprocessing多进程-process模块(一) [python]详解multiprocessing多进程-Pool进程池模块(二) [python]详解multip ...

最新文章

  1. oracle如何查询虚拟列,Oracle11g新特性之--虚拟列(VirtualColumn)
  2. jQuery与其它库冲突的解决方法(转)
  3. AI公开课:19.02.20 雷鸣教授《人工智能革命与机遇》课堂笔记以及个人感悟
  4. 动态规划之——最长公共子序列(nyoj36)
  5. php限制小程序访问,PHP投票小程序,防超时,防IP限制
  6. Wait Event Disk file operations I/O
  7. 成功最快的就是改变你这个思维,拥有这个全新的思维
  8. 多进程服务器中,epoll的创建应该在创建子进程之后
  9. 110kV终端变电站电气部分设计
  10. 【工具推荐】在线latex公式编辑器(可用鼠标交互)
  11. 互联网金融爬虫怎么写-第一课 p2p网贷爬虫(XPath入门)
  12. 迅雷极速版服务器未响应,迅雷极速版频繁崩溃,求大神帮忙
  13. 科研工具--论文-作者-影响力等-精准制导-检索网站
  14. Photoshop小技巧 (去掉照片中多余的人物)
  15. ubuntu系统执行lunch时报错的处理方法
  16. golang 字符串拼接 字符串数组转字符串
  17. 安恒西湖论剑周周练Reverse刮开有奖WP
  18. error:无法解析的外部符号 “public: __thiscall ···该符号在函数···中被引用”
  19. 快速提高数学成绩的奇书《巧学妙解王》高中数学!
  20. 【机器学习】粗糙集(Rough Set Approach)

热门文章

  1. 苹果退款_苹果充值退款什么意思
  2. 转载--成功应聘Intel的真实经历
  3. cshtml中文乱码
  4. 使用cordova + vue搭建混合app框架
  5. 88-Spring Boot详解
  6. ESP32 单片机学习笔记 - 06 - (以太网)Ethernet转Wifi
  7. 算法:数据流中的中位数
  8. linux bochs 网络,Linux下Bochs的使用(转载)
  9. 一文读懂Diffusion model
  10. perror()函数