Python二叉树的三种深度优先遍历

2023-11-10

Python二叉树的三种深度优先遍历

一、广度优先遍历和深度优先遍历

对二叉树进行遍历(traversal)是指依次对树中每个节点进行访问,在遍历的过程中实现需要的业务。

对树的遍历方式有广度优先遍历和深度优先遍历两种方式。广度优先一般用队列的方式,对树从上到下逐层遍历,每一层从左到右依次遍历。深度优先一般用递归的方式,遍历时会先尽可能深地遍历,直到叶节点。

在实现完全二叉树时,向完全二叉树中添加数据就是使用广度优先遍历,通过广度优先遍历找到第一个空位,将节点加到此位置。

参考:https://blog.csdn.net/weixin_43790276/article/details/104033490

对于一颗二叉树,深度优先遍历(Depth First Search)是沿着树的深度遍历树的节点,尽可能深地搜索树的分支。本文的重点是深度优先遍历的三种方式。

深度优先遍历有三种方式。这三种遍历方式分别叫做先序遍历(preorder)、中序遍历(inorder)和后序遍历(postorder),这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。

1. 先序遍历,也叫先根遍历。在先序遍历中,先访问树的根节点,然后递归使用先序遍历访问左子树,最后再递归使用先序遍历访问右子树。遍历顺序为:根节点 -> 左子树 -> 右子树。

2. 中序遍历,也叫中根遍历。在中序遍历中,先递归使用中序遍历访问左子树,然后访问树的根节点,最后再递归使用中序遍历访问右子树。遍历顺序为:左子树 -> 根节点 -> 右子树。

3. 后序遍历,也叫后根遍历。在后序遍历中,先递归使用后序遍历访问左子树,然后递归使用后序遍历访问右子树,最后再访问树的根节点。遍历顺序为:左子树 -> 右子树 -> 根节点。

在这三种遍历方式中,有两点需要注意,一是左右都是说子树,而不是子节点,所以遍历时不能理解成子节点。二是要递归地用相同的遍历方式处理子树,如先序遍历中,要遍历完整个左子树后,才开始遍历右子树,且不管左子树还是右子树,都是先序遍历。

不难发现,先、中、后都是针对访问根节点的先中后来说的,三种遍历方式的另一个名称就是因此而得。

二、实现一棵二叉树

要对二叉树进行遍历,需要先创建一棵二叉树,这里直接使用之前实现完全二叉树的代码,代码如下。

# coding=utf-8
class Node(object):
    def __init__(self, data):
        self.data = data
        self.parent = None
        self.left_child = None
        self.right_child = None


class TreeQueue(object):
    def __init__(self):
        self.__members = list()

    def is_empty(self):
        return not len(self.__members)

    def enter(self, data):
        self.__members.insert(0, data)

    def outer(self):
        if self.is_empty():
            return
        return self.__members.pop()


class PerfectBinaryTree(object):

    def __init__(self):
        self.__root = None

    def is_empty(self):
        return not self.__root

    def append(self, data):
        node = Node(data)
        if self.is_empty():
            self.__root = node
            return
        queue = TreeQueue()
        queue.enter(self.__root)
        while not queue.is_empty():
            cur = queue.outer()
            if cur.left_child is None:
                cur.left_child = node
                node.parent = cur
                return
            queue.enter(cur.left_child)
            if cur.right_child is None:
                cur.right_child = node
                node.parent = cur
                return
            queue.enter(cur.right_child)

    def show(self):
        if self.is_empty():
            print('空二叉树')
            return
        queue = TreeQueue()
        queue.enter(self.__root)
        while not queue.is_empty():
            cur = queue.outer()
            print(cur.data, end=' ')
            if cur.left_child is not None:
                queue.enter(cur.left_child)
            if cur.right_child is not None:
                queue.enter(cur.right_child)
        print()

    def get_root(self):
        return self.__root

代码里使用队列的方式实现了广度优先遍历,也叫层次遍历。

在二叉树深度优先遍历的三种方式中,都要使用递归的方式,而触发递归都是从根节点开始的,所以增加一个获取根节点的方法 get_root() ,供遍历时使用。

三、先序遍历

以上图为例,用先序遍历的方式对这棵树进行遍历,先访问根节点 A ,然后对左子树先序遍历,左子树的根节点是节点 B,再对 B 的左子树先序遍历,B 的左子树的根节点是节点 D,再对 D 的左子树先序遍历,D 的左子树的根节点是节点 H。H 没有子树了,D 的左子树遍历完了,对 D 的右子树先序遍历,D 的右子树的根节点是节点 I,D 的右子树也遍历完了。这时 B 的左子树也遍历完了,对 B 的右子树先序遍历,B 的右子树的根节点是节点 E,再对 E 的左子树先序遍历,E 的左子树的根节点是节点 J,E 的左子树遍历完了,E 没有右子树,所以 B 的右子树也遍历完了。看整棵树,根节点 A 的左子树遍历完了,再对 A 的右子树先序遍历,A 的右子树的根节点是节点 C ,再对 C 的左子树先序遍历,C 的左子树的根节点是节点 F,C 的左子树遍历完了,对 C 的右子树先序遍历,C 的右子树的根节点是节点 G ,到这里,整棵树就遍历完了。

先序遍历的结果是:A B D H I E J C F G 。

这个过程很长,我把全部步骤写了下来,这就是整个递归的过程,可以看到具体的每一个步骤,嫌烦可以跳过。

接下来用代码实现:

# 先根遍历(先序遍历)
def preorder_traversal(root):
    if root is None:
        return
    print(root.data, end=' ')
    preorder_traversal(root.left_child)
    preorder_traversal(root.right_child)

代码很简单,就是先处理(打印)根节点,然后递归处理左子树,最后再递归处理右子树。

四、中序遍历

有了先序遍历的逐步记录,中序遍历就不再赘述了。

对于上图中的二叉树,中序遍历的结果是:H D I B J E A F C G 。

代码如下:

# 中根遍历(中序遍历)
def inorder_traversal(root):
    if root is None:
        return
    inorder_traversal(root.left_child)
    print(root.data, end=' ')
    inorder_traversal(root.right_child)

代码也很简单,先递归处理(打印)左子树,然后处理根节点,最后再递归处理右子树。

五、后序遍历

同理,将根节点的处理放到最后,就是后序遍历了,这里也不再赘述过程。

还是上图中的二叉树,后序遍历的结果是:H I D J E B F G C A

代码如下:

# 后根遍历(后序遍历)
def postorder_traversal(root):
    if root is None:
        return
    postorder_traversal(root.left_child)
    postorder_traversal(root.right_child)
    print(root.data, end=' ')

代码还是很简单,先递归处理(打印)左子树,然后递归处理右子树,最后再处理根节点。

在这三种遍历方式中,理解了递归的思想,这三个函数就非常好理解了。

下面将层次遍历和三种深度优先遍历的运行结果放到一起进行比较。

if __name__ == '__main__':
    tree = PerfectBinaryTree()
    for alpha in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']:
        tree.append(alpha)
    print('层次遍历: ', end='')
    tree.show()
    print('先序遍历: ', end='')
    preorder_traversal(tree.get_root())
    print()
    print('中序遍历: ', end='')
    inorder_traversal(tree.get_root())
    print()
    print('后序遍历: ', end='')
    postorder_traversal(tree.get_root())
    print()

运行结果:

层次遍历: A B C D E F G H I J 
先序遍历: A B D H I E J C F G 
中序遍历: H D I B J E A F C G 
后序遍历: H I D J E B F G C A 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python二叉树的三种深度优先遍历 的相关文章

  • 软件测试项目【金融、银行、电商、商城】

    项目经验 案例一 项目时间 2016 08 2017 07 项目名称 小花钱包 Web 项目描述 项目介绍 这个产品产是互联网金融理财服务平台 既可以发起投标 也可以借款 提供定期理财 活期理财等多种产品 平台主要有投资人 借款人 系统录入
  • 【虹软24届校招正式批】本周算法&;开发第二波笔试来袭

    今日更新提醒 看过了招聘信息 快来用牛客直投官网吧 打call 一键直投 给自己多一次面试机会 赞 移动端 https mnowpick nowcoder com m m 立得空间 C 开发技术面 1 项目中的线程池问题2 指针引用区别3

随机推荐

  • 1.fastadmin之Log日志使用

    要开始用fastadmin做小程序的后台 怎么说 这个框架封装的很好 对于我这种新手渣渣不太友好 惆怅 首先来谈谈日志的使用吧 如何打个log 一 概念 1 在控制器中声明 use think Log 2 log的方法 一般我使用log w
  • Spring Cloud获取本机IP地址

    最新的Spring Cloud获取本机的IP地址的配置文件如下 eureka instance hostname spring cloud client ip address lease renewal interval in second
  • 用Langchain构建一个阅读助手

    LangChain 是一个强大的框架 可以简化构建高级语言模型应用程序的过程 01 什么是Langchain LangChain是一个强大的框架 旨在帮助开发人员使用语言模型构建端到端的应用程序 它提供了一套工具 组件和接口 可简化创建由大
  • STM32CubeM的搭建以及基于HAL库实现LED闪烁

    文章目录 一 STM32的开发环境的搭建 1 安装jdk环境 2 安装STM32CubeMX 3 安装固件库 4 安装MDK5软件 二 利用工具生成点亮LED灯的代码 三 MDK5生成 hex文件 四 程序烧录 五 运行结果 六 MDK5模
  • 基于SimGAN网络的人眼数据生成方法_SimGAN原理_参考代码

    注 此文为复现sim GAN 参考了一些论文 博客 如有侵权请联系 我附上原出处 由于一些格式原因 文章有些部分会比较乱 请见谅 Learning from Simulated and Unsupervised Images through
  • 5个你不可不知的IE的bug及其解决方案

    E令人咬牙切齿的bug不胜枚举 其中IE6更是臭名昭著 令人发指 这里总结出IE下最为严重的5个bug 及其应对方案 1 IE6下无法显示png格式的透明信息 这个bug是众多网页设计师的噩梦 虽然可以采用gif代替 但是gif的表现力实在
  • Ubuntu之Docker安装

    1 先卸载旧版 如果没有的话 就直接执行第二步 apt get remove docker docker engine docker io containerd runc 这个命令用于在 Ubuntu 和其他基于 Debian 的 Linu
  • qt 储存库

    手动添加 储存库要定位一个储存有QT在线安装镜像的地址 打开 http download qt io static mirrorlist 这个网址 显示了各国的qt镜像站点 点击 HTTP 最终进到 online repository ht
  • [C语言]浮点型在内存中的存储

    在上一篇文章 我们讲述了整型在内存中的存储 这篇文章我们就一起来看一下 浮点型在内存中的存储 回顾 整型在内存中的存储 C语言 和我一起来认识 整型在内存中的存储 HY PIGIE的博客 CSDN博客 目录 1 浮点数家族 2 整型和浮点型
  • Envi5.3——高分二号PMS数据预处理

    首先第一步 打开数据open 以TIFF格式打开 开始进行正射校正 RPC正射工作流程 我们先对多光谱进行校正 输入需正射校正文件和DEM文件 在这里我们不用自带的2010年的DEM文件 点击下一步 在高级控制面板 输出像素大小为4米 图像
  • 用于非线性时间序列预测的稀疏局部线性和邻域嵌入(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 本文提出了一种基于字典的L1范数稀疏编码
  • 基于SpringBoot的特色农产品销售设计与实现

    摘 要 目前市场上众多的特色农产品销售系统存在种种不足 比如系统无需登录即可查看农产品卖家的联系方式 并且交易大多为线下交易 很难实现线上购买 物流配送 线上收货收款的功能 本系统提供线上购买服务 使用数据库进行订单管理 设计优化交互界面
  • 【成电860考研】经验贴汇总(公共课+专业课+复试)-扒遍所有网站:信软群、王道、知乎、csdn等,截止21年7月整理出的所有帖子-共15篇

    单词哥 2020跨考 背景 记得 18 年底的时候 好朋友那年考研 我闲的无事就拿他买的英 语一真题做了下 忘了哪一年的题了 不过结果还可以 这也为后来 辞职考研埋了根 由于长期从事英语相关的工作 而又想要圆自己大 学时学计算机的梦 说到底
  • es 中关于 term,match, text, keyword

    转自 https blog csdn net qq 38043440 article details 101678677 最近项目中使用了ElasticSearch 在使用基本的查询功能的时候 遇到些头疼的事情 有时候数据明明存在 用ter
  • ES命令: “track_total_hits“:true

    搜索type全部数据 GET test movie search 结果 took 2 耗费时间 毫秒 timed out false 是否超时 shards total 5 发送给全部5个分片 successful 5 skipped 0
  • vlc详细使用说明

    vlc的全名是Video Lan Client 是一个开源的 跨平台的视频播放器 VLC支持大量的音视频传输 封装和编码格式 完整的功能特性列表可以在这里获得http www videolan org vlc features html 下
  • 小米蓝牙耳机使用说明_小米真无线蓝牙耳机Air2 SE评测

    很多人都会把 小米Air2 SE 这款耳机 当成是上一代的阉割版本 其实完全没必要这么想 因为他们除了耳机有点像之外 其它几乎全不一样 甚至当两款独立的产品也是没问题的 这款耳机根据我的分析和体验 我觉得它在音质上和小米Air2s 几乎是差
  • React——简介、JSX、组件、传值 React Props、状态 React State

    环境搭建 npm i g create react app create react app myapp cd myapp npm start 一 简介 1 简介 React主要用于构建UI 你可以在React里传递多种类型的参数 如声明代
  • spring boot获取datasource为null_Spring讲解九

    Spring JDBC 数据访问 Spring JDBC是Spring所提供的持久层技术 它的主要目标是降低使用JDBC API的门槛 以一种更直接 更简介 更简单的方式使用JDBC API 在Spring JDBC里 仅需做那些与业务相关
  • Python二叉树的三种深度优先遍历

    Python二叉树的三种深度优先遍历 一 广度优先遍历和深度优先遍历 对二叉树进行遍历 traversal 是指依次对树中每个节点进行访问 在遍历的过程中实现需要的业务 对树的遍历方式有广度优先遍历和深度优先遍历两种方式 广度优先一般用队列