树结构--介绍--二叉树遍历的递归实现

news2024/11/24 16:59:29

 

目录

树 

树的学术名词

树的种类

 二叉树的遍历

算法实现

遍历命名

二叉树的中序遍历

二叉树的后序遍历

二叉树的后序遍历迭代算法

 二叉树的前序遍历

二叉树的前序遍历迭代算法

 


树封面

树 

是一种非线性的数据结构,它是由n(n≥0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

  • 每个节点有零个或多个子节点;
  • 没有父节点的节点称为根节点;
  • 每一个非根节点有且只有一个父节点;
  • 除了根节点外,每个子节点可以分为多个不相交的子树

image-20220909102214728

树的学术名词

  • 根节点(root): 树的最上层的节点,任何非空的树都有一个节点
  • 路径(path): 从起始节点到终止节点经历过的边
  • 父亲(parent):除了根节点,每个节点的上一层边连接的节点就是它的父亲(节点)
  • 孩子(children): 每个节点由边指向的下一层节点
  • 兄弟(siblings): 同一个父亲并且处在同一层的节点
  • 子树(subtree): 每个节点包含它所有的后代组成的子树
  • 叶子节点(leaf node): 没有孩子的节点成为叶子节点

树的种类

无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树;

有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树;

二叉树:每个节点最多含有两个子树的树称为二叉树;

满二叉树:所有节点均含有两个子树的树被称为满二叉树;

完全二叉树:除最后一层外,所有层都是满节点,且最后一层缺右边连续节点的二叉树称为完全二叉树;

哈夫曼树(最优二叉树):带权路径最短的二叉树称为哈夫曼树或最优二叉树。

image-20220912170946925

 二叉树的遍历

所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问

访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础

算法实现

从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:

  • 访问节点的本身(Node)
  • 遍历该节点的左子树(L)
  • 遍历该节点的右子树 (R)

以上三种操作拥有六种执行顺序:

NLR,LNR,LRN,NRL,RNL,RLN。

但是注意前三种次序和后三种次序对称,所以我们只学习前三种次序

image-20220912185718782

遍历命名

根据访问结点操作发生位置命名:

  • NLR:二叉树的前序遍历(Preorder Traversal 亦称(先序遍历))

    访问根结点的操作发生在遍历其左右子树之前

  • LNR:二叉树的中序遍历(Inorder Traversal)

    访问根结点的操作发生在遍历其左右子树之中(间)

  • LRN:二叉树的后序遍历(Postorder Traversal)

    访问根结点的操作发生在遍历其左右子树之后

     

二叉树的中序遍历

若二叉树非空,则依次执行如下操作:

  1. 遍历左子树
  2. 访问根节点
  3. 遍历右子树

image-20220912185750188

# Definition for a binary tree node.
# class TreeNode:
#   def __init__(self, val=0, left=None, right=None):
#     self.val = val
#     self.left = left
#     self.right = right
class Solution:
  def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    # 左 根 右
    def inorder(root : TreeNode):
      if not root:
        return
      
      inorder(root.left)
      res.append(root.val)
      inorder(root.right)




    res = list()
    inorder(root)
    return res

 

二叉树的后序遍历

若二叉树非空,则依次执行如下操作:

  1. 遍历左子树
  2. 遍历右子树
  3. 访问根节点

image-20220912185833626

# Definition for a binary tree node.
# class TreeNode:
#   def __init__(self, val=0, left=None, right=None):
#     self.val = val
#     self.left = left
#     self.right = right
class Solution:
  def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    # 后序遍历的顺序:左 右 根
    def postorder(root : TreeNode):
      if not root:
        return
      
      postorder(root.left)
      postorder(root.right)
      res.append(root.val)




    res = list()
    postorder(root)
    return res

二叉树的后序遍历迭代算法

  1. 建立一个栈,用来存储节点。

  2. 根据根右左的顺序将节点依次压入栈中,在压入栈中的同时,按照顺序把节点里的元素依次压入栈中。输出完毕之后按照顺序弹栈。

  3. 将答案数组进行反转,得到左右根顺序的数组

  4. 输出答案

    image-20220913114354933

期望结果:[9,5,7,4,3]

# Definition for a binary tree node.
# class TreeNode:
#   def __init__(self, val=0, left=None, right=None):
#     self.val = val
#     self.left = left
#     self.right = right
class Solution:
  def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    res = []
    stack = []
    while root or stack:
      while root:
        res.append(root.val)
        stack.append(root)
        root = root.right
      root = stack.pop().left #根 右 左的顺序


    res.reverse() 
    return res

 二叉树的前序遍历

若二叉树非空,则依次执行如下操作:

  1. 访问根节点

  2. 遍历左子树

  3. 遍历右子树

    image-20220912185519144

     

    class Solution:
      def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 创建一个集合存储数据
        res = []
        def preorder(root:TreeNode):
          # 判断root是否有值
          if not root:
            return
          else:
            # 获取根节点
            res.append(root.val)
            # 获取左节点
            preorder(root.left)
            # 获取右节点
            preorder(root.right)
        preorder(root)
        return res
    

    二叉树的前序遍历迭代算法

  4. 建立一个栈,用来存储节点。
  5. 根据左右根的顺序将节点依次压入栈中,在压入栈中的同时,按照顺序把节点里的元素依次压入栈中。输出完毕之后按照顺序弹栈。
  6. 输出答案。
class Solution:
  def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    # 创建res存储结果
    res = []
    stack = [] # 存储分支节点
    # 只要root有数据 或者stack的数据
    while root or stack:
      # 只要root有数据,第一轮循环把左节点搞定
      while root:
        res.append(root.val)
        stack.append(root)
        # 获取左节点
        root = root.left
      # 取出右节点,遍历
      root = stack.pop().right
    return res

 

 

 

 

 

 

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

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

相关文章

Java基础篇--基本数据类型

目录 前言: 内置数据类型 类型默认值 示例: 内置数据类型转换 自动类型转换(隐式类型转换): 强制类型转换(显式类型转换): 隐含强制类型转换: 引用类型 前言: …

Java基础练习八(二维数组)

1.装水问题 有一个 异形 容器,用一个 n * n 的二维数组来表示。其中 1 表示容器实心部分, 0 表示空心部分。现使用此容器装水,能装多少水(每个元素都表示一份水,只有有挡板的部分能装水)? publi…

【学习】若依源码(前后端分离版)之 “ 获取角色权限信息及动态路由”

大型纪录片:学习若依源码(前后端分离版)之 “ 获取角色权限信息及动态路由” 获取用户信息获取路由信息 承接上回,我们发现在login请求后面跟了两个请求,今天我们就来了解一下两个请求的含义。 获取用户信息 先看 ‘…

Vulhub之Apache HTTPD 换行解析漏洞(CVE-2017-15715)

Apache HTTPD是一款HTTP服务器,它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中存在一个解析漏洞,在解析PHP时,1.php\x0A将被按照PHP后缀进行解析,导致绕过一些服务器的安全策略。 1、docker-compose build、docker-compo…

yolov5的报错

【定期水一期】 (这个问题很抓马,可以看一下这篇文章:Git Bash 教程!【不是所有人都会用Git】) 一:没有cv2这个模块 解决方案: pip install opencv-python -i http://pypi.douban.com/simple/…

Java用方法实现数组拷贝

Java用方法实现数组拷贝 需求分析代码实现小结Time 需求分析 1.首先,考虑方法是否需要接收数据处理? 该方法的目的是拷贝数组,拷贝哪一个数组呢? 需要调用者传递 所以,参数应该是一个数组 2.接着,考虑方法是…

k8s常用资源管理

目录 Pod(容器组):Pod是Kubernetes中最小的部署单元,可以包含一个或多个容器。Pod提供了一种逻辑上的封装,使得容器可以一起共享网络和存储资源 1、创建一个pod 2、pod管理 pod操作 Pod(容器组&#xff…

单机游戏防破解方案解析

近年来,游戏市场用户规模趋于稳定,游戏市场进入了存量时代,各赛道“人满为患”,如何在一片红海中站稳脚跟成了厂商的必修课。 而在快节奏的社会环境下,脱离了网游社交粘性,主打清爽、自由的单机游戏&#…

软考圈地震!2023年下半年软考改为机考,报名时间推迟到9月4日

【1】通知原文 关于2023年下半年计算机软件资格考试有关工作调整的通知 各省、自治区、直辖市及计划单列市、新疆生产建设兵团,香港、澳门计算机软件资格考试考务管理机构: 为全面做好计算机软件资格考试安全防控工作,确保考试公正、公平。现将有关工…

【C语言学习】构造函数求出1到10、20到30、40到50的三个和

求出1到10、20到30、40到50的三个和 代码一&#xff1a;代码复制 #include<stdio.h> int main() {int i;int sum;for(i1,sum0; i<10; i){sum sum i;}printf("%d到%d的和是%d\n", 1, 10, sum);for(i20,sum0; i<30; i){sum sum i;}printf("%d到…

易服客工作室:如何创建有用的内容日历

利用技巧和工具优化您的内容营销效率和效果。创建一个内容日历&#xff0c;您的整个团队都会从中受益&#xff01; 欢迎来到熙熙攘攘、瞬息万变的内容营销世界&#xff0c;在这里&#xff0c;截止日期到来的速度比喝咖啡的猎豹还要快。 现在&#xff0c;想象一下在没有地图、…

家电用PCM板:市场现状研究分析与发展前景预测

家电PCM板属于一种兴起不久的功能性复合材料。属于家电复合外观材料中占比较大的一种。家电复合外观材料主要分为覆膜板&#xff08;VCM&#xff09;系列和有机涂层板&#xff08;PCM&#xff09;系列两大类&#xff1a;VCM系列表面复合各类功能性薄膜&#xff0c;可根据需要实…

湘大 XTU OJ 1214 A+B IV 题解:数位移动的本质+布尔变量标记+朴素模拟

一、链接 AB IV 二、题目 题目描述 小明喜欢做ab的算术&#xff0c;但是他经常忘记把末位对齐&#xff0c;再进行加&#xff0c;所以&#xff0c;经常会算错。 比如1213&#xff0c;他把12左移了1位&#xff0c;结果变成了133。 小明已经算了一些等式&#xff0c;请计算一下…

棒球游戏产业的发展·棒球1号位

棒球游戏产业的发展 1. 棒球游戏产业概述 棒球游戏产业的定义 棒球游戏产业是一个包罗万象的产业集群&#xff0c;涵盖了从基础设施到高端设备&#xff0c;从前沿技术研发到市场推广等各个环节。这个产业的繁荣得益于棒球运动的普及&#xff0c;人们对于棒球游戏的热情以及对…

0基础学C#笔记09:希尔排序法

文章目录 前言一、希尔排序的思想二、使用步骤总结前言 希尔排序可以说是插入排序的一种变种。无论是插入排序还是冒泡排序,如果数组的最大值刚好是在第一位,要将它挪到正确的位置就需要 n - 1 次移动。也就是说,原数组的一个元素如果距离它正确的位置很远的话,则需要与相…

linux cp -rpf指令

cp -rpf #强行递归复制/etc目录到/mist目录中&#xff0c;并保持源目录的权限等信息不变。 有点类似于打patch&#xff0c;不会改变已有的内容。

一次面试下来Android Framework 层的源码就问了4轮

说起字节跳动的这次面试经历&#xff0c;真的是现在都让我感觉背脊发凉&#xff0c;简直被面试官折磨的太难受了。虽然已经工作了七年&#xff0c;但是也只是纯粹的在写业务&#xff0c;对底层并没有一个很深的认识&#xff0c;这次面试经历直接的让我感受到我和那些一线大厂开…

揭秘!亚马逊美国站的热门品类有哪些?

做亚马逊跨境电商&#xff0c;做热门的品类是很最重要的&#xff0c;这样的市场需求量大&#xff0c;产品才能够更好的销售出去&#xff0c;不然的话选择冷门品类&#xff0c;就算你做到了第一&#xff0c;那销量一样不高。 在亚马逊跨境电商很多站点内都有热门品类&#xff0…

gateway做token校验

本文使用springcloud的gateway做token校验 登录的本质&#xff1a;拿用户名和密码 换 token。 token会返回给浏览器&#xff08;存储&#xff09;&#xff0c;当访问的时候&#xff0c;携带token 发起请求。 token校验图 引入redis依赖 <dependency><groupId>or…

vue3多条件搜索功能

搜索功能在后台管理页面中非常常见&#xff0c;本篇就着重讲一下vue3-admin-element框架中如何实现一个顶部多条件搜索功能 一、首先需要在vue页面的<template></template>中写入对应的结构 <!-- 搜索 --><div style"display: flex; justify-content…