【数据结构与算法】二叉树的遍历及还原

树形结构 - 有向无环图

树是图的一种。

  • 树形结构有一个根节点
  • 树形结构没有回路
  • 根节点:A
  • 叶子节点:下边没有其他节点了
  • 节点:既不是根节点,又不是叶子节点的普通节点
  • 树的度:这棵树最多叉的节点有多少叉,这棵树的度就为多少
  • 树的深度:最深有几层就是几

二叉树:

image.png

  1. 二叉树的根节点A

  2. 子节点:某个节点下面的节点

  3. 父节点:上级节点

  4. 叶子节点:CDE

  5. 节点:B

  6. 满二叉树:(1)所有的叶子节点都在最底层 (2)每个非叶子节点都有两个子节点

  7. 完全二叉树:

    国内定义:(1)叶子节点都在最后一层或倒数第二层(2)叶子节点都向左聚拢

    国际定义:(1)叶子节点都在最后一层或倒数第二层(2)如果有叶子节点,就必然有两个叶子节点

遍历二叉树

  • 前序遍历:根左右
  • 中序遍历:左根右
  • 后序遍历:左右根

image.png

前序遍历

function Node(value) {
    this.value = value
    this.left = null
    this.right = null
}

let a = new Node('a')
let b = new Node('b')
let c = new Node('c')
let d = new Node('d')
let e = new Node('e')
let f = new Node('f')
let g = new Node('g')
a.left = c
a.right = b
c.left = f
c.right = g
b.left = d
b.right = e

function preTraversal(root) {
    if (root == null) return
    console.log(root.value)
    preTraversal(root.left)
    preTraversal(root.right)
}
preTraversal(a)

中序遍历

function Node(value) {
    this.value = value
    this.left = null
    this.right = null
}

let a = new Node('a')
let b = new Node('b')
let c = new Node('c')
let d = new Node('d')
let e = new Node('e')
let f = new Node('f')
let g = new Node('g')
a.left = c
a.right = b
c.left = f
c.right = g
b.left = d
b.right = e

function inTraversal(root) {
    if (root == null) return
    inTraversal(root.left)
    console.log(root.value)
    inTraversal(root.right)
}
inTraversal(a)

后序遍历

function Node(value) {
    this.value = value
    this.left = null
    this.right = null
}

let a = new Node('a')
let b = new Node('b')
let c = new Node('c')
let d = new Node('d')
let e = new Node('e')
let f = new Node('f')
let g = new Node('g')
a.left = c
a.right = b
c.left = f
c.right = g
b.left = d
b.right = e

function postTraversal(root) {
    if (root == null) return
    postTraversal(root.left)
    postTraversal(root.right)
    console.log(root.value)
}
postTraversal(a)

还原二叉树

给出前中序还原二叉树

let preTraverse = ['a', 'c', 'f', 'g', 'b', 'd', 'e'];
let inTraverse = ['f', 'c', 'g', 'a', 'd', 'b', 'e'];

function Node(value) {
    this.value = value
    this.left = null
    this.right = null
}

function binaryTree(preTraverse, inTraverse) {
    if (preTraverse == null || inTraverse == null || preTraverse.length == 0 || inTraverse.length == 0 || preTraverse.length != inTraverse.length) return
    let  root = new Node(preTraverse[0])
    // 找到根节点在中序遍历中的位置
    let index = inTraverse.indexOf(root.value)
    // 先序序遍的左子树
    let preLeft = preTraverse.slice(1, 1 + index)
    // 先序遍历的右子树
    let preRight = preTraverse.slice(1 + index, preTraverse.length)
    // 中序遍历的左子树
    let inLeft = inTraverse.slice(0, index)
    // 中序遍历的右子树
    let inRight = inTraverse.slice(index + 1, inTraverse.length)
    root.left = binaryTree(preLeft, inLeft)
    root.right = binaryTree(preRight, inRight)
    return root
}

let root = binaryTree(preTraverse, inTraverse)
console.log(root.left)
console.log(root.right)

image.png

给出中后序还原二叉树

let postTraverse = ['f', 'g', 'c', 'd', 'e', 'b', 'a'];
let inTraverse = ['f', 'c', 'g', 'a', 'd', 'b', 'e'];

function Node(value) {
    this.value = value
    this.left = null
    this.right = null
}

function binaryTree(postTraverse, inTraverse) {
    if (postTraverse == null || inTraverse == null || postTraverse.length == 0 || inTraverse.length == 0 || postTraverse.length != inTraverse.length) return
    let  root = new Node(postTraverse[postTraverse.length - 1])
    // 找到根节点在中序遍历中的位置
    let index = inTraverse.indexOf(root.value)
    // 后序序遍的左子树
    let postLeft = postTraverse.slice(0, index)
    // 后序遍历的右子树
    let postRight = inTraverse.slice(index, postTraverse.length - 1)
    // 中序遍历的左子树
    let inLeft = inTraverse.slice(0, index)
    // 中序遍历的右子树
    let inRight = inTraverse.slice(index + 1, inTraverse.length)
    root.left = binaryTree(postLeft, inLeft)
    root.right = binaryTree(postRight, inRight)
    return root
}

let root = binaryTree(postTraverse, inTraverse)
console.log(root.left)
console.log(root.right)

image.png

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ROS中IMU惯性测量单元

一、IMU惯性测量单元消息包 IMU 是安装在机器人内部的一种传感器模块,用于测量机器人的空间姿态。 IMU的消息包定义在sensor_msgs包中的Imu中。头部是header,记录了消息发送的时间戳和坐标系ID。第二个是角速度。第三个是矢量加速度。三个数据成员都各…

机器学习每周挑战——旅游景点数据分析

数据的截图,数据的说明: # 字段 数据类型 # 城市 string # 名称 string # 星级 string # 评分 float # 价格 float # 销量 int # 省/市/区 string # 坐标 string # 简介 string # 是否免费 bool # 具体地址 string拿到数据…

Godot 4 教程《勇者传说》依赖注入 学习笔记(0):环境配置

文章目录 前言相关地址环境配置初始化环境配置文件夹结构代码结构代码运行 资源文件导入像素风格窗口环境设置背景设置,Tileap使用自动TileMap 人物场景动画节点添加站立节点添加移动动画添加 通过依赖注入获取Godot的全局属性项目声明 当前项目逻辑讲解角色下降添加代码位置问…

MCGS学习——水位控制

要求 插入一个水罐,液位最大值为37插入一个滑动输入器,用来调节水罐水位,滑动输入器最大调节为液位最大值,并能清楚的显示出液位情况用仪表显示水位变化情况,仪表最大显示设置直观清楚方便读数,主划线为小…

CAJViewer8.1下载地址及安装教程

CAJViewer是中国学术期刊(CAJ)全文数据库的专用阅读软件。CAJViewer是中国知识资源总库(CNKI)开发的一款软件,旨在方便用户在线阅读和下载CAJ数据库中的学术论文、期刊和会议论文等文献资源。 CAJViewer具有直观的界面…

Linux系统——Mysql数据库锁的拓展

目录 一、锁的概述 二、锁的分类 1.按锁粒度分类 2.按性能分类 3.按对数据库操作类型 三、全局锁 1.定义 2.操作 3.特点 四、表级锁 1.表级锁分类 2.表锁分类 2.1表共享读锁(read lock) 2.2表独占写锁(write lock) …

随便注【强网杯2019】

大佬的完整wp:buuctf-web-[强网杯 2019]随便注-wp_取材于某次真实环境渗透,只说一句话:开发和安全缺一不可-CSDN博客 知识点: 单引号字符型绕过堆叠注入 可以执行多条语句multi_query():该函数可能引发堆叠注入handler用法 mysql专属&#…

计算机基础系列 —— 虚拟机代码翻译器(2)

I believe that at the end of the century the use of words and general educated opinion will have altered so much that one will be able to speak of machines thinking without expecting to be contradicted. —— Alan Turing 文中提到的所有实现都可以参考&#xf…

【MATLAB源码-第173期】基于matlab的RS编码的2FSK通信系统误码率仿真,通过AWGN信道输出误码率曲线。

操作环境: MATLAB 2022a 1、算法描述 通信系统的基本框架 在现代通信系统中,数据的传输通常涉及四个基本步骤:源编码、信道编码、调制和传输。源编码主要负责压缩数据,减少传输的数据量。信道编码则通过添加冗余信息来提高传输…

【Blockchain】区块链浏览器 | 以太坊Etherscan比特币Blockchain门罗币Monero

区块链浏览器概述 区块链浏览器是一种软件,它使用API(应用程序编程接口)和区块链节点从区块链中提取各种数据,然后使用数据库来排列搜索到的数据,并以可搜索的格式将数据呈现给用户。 用户的输入是资源管理器上的可搜索项,然后通过数据库上…

【力扣hot100】128-最长连续序列、283-移动零

128. 最长连续序列 import java.util.*;public class Test {public static void main(String[] args) {int[] nums {0, 3, 7, 2, 5, 8, 4, 6, 0, 1};int res new Solution().longestConsecutive(nums);System.out.println(res);} }class Solution {public int longestConsecu…

3.31学习总结

算法 解题思路 使用dfs,对蛋糕每层可能的高度和半径进行穷举.通过观察我们可以知道第一层的圆面积是它上面所有蛋糕层的圆面积之和,所以我们只要去求每层的侧面积就行了. 因为题目要求Ri > Ri1且Hi > Hi1,所以我们可以求出每层的最小体积和侧面积,用两个数组分别储存起来…

教你一键轻松领取阿里云优惠券

随着云计算的普及,越来越多的企业和个人开始选择使用云服务。阿里云作为国内领先的云计算服务提供商,以其稳定、高效、安全的服务赢得了广大用户的信赖。为了吸引用户上云,阿里云推出了优惠券活动,本文将教大家如何一键领取阿里云…

【Linux】深入理解进程状态、优先级和调度:Linux 内核中的实现原理探析

文章目录 前言1. 进程状态1.1. 轻量进程排队这件事情——队列1.2. 进程状态的表述及其影响:1.3. 挂起状态及处理:1.4.理解 Linux 内核源代码中的状态表述: 2. 进程优先级Linux 为什么要调整优先级是要受限的? 3. Linux的调度与切换…

Typora下载激活方案

一、下载 1.在typora官网下载最新版本,并安装: 官网地址 2.获取激活工具 感谢Typora激活方法(2023年最新版) - AI小智的文章 - 知乎 https://zhuanlan.zhihu.com/p/669618741 二、激活 1.把两个.exe文件复制到typora安装目录下 2.在typor…

ubuntu下给不同串口设置别名

目录 一、绑定设备ID 1.查看设备ID 2.编写usev规则 3.重新加载usev规则 4.查看 二、绑定USB端口号 1.先插入一个串口,查看USB设备信息 2.查看USB转串口信息 3.编写usev规则 4.重新加载usev规则 5.查看 在Ubuntu环境下,有时候工控机或者arm开…

推挽输出与开漏输出

推挽输出与开漏输出 文章目录 推挽输出与开漏输出前言一、推挽输出二、开漏输出总结 前言 在使用GPIO口时,会遇到两种配置,一种叫推挽输出,一种叫开漏输出,今天就简聊一聊这两种模式的差异和选择。 一、推挽输出 如图所示&#…

Lazarus远控组件NukeSped分析

静态信息: 样本md5:9b656f5d7e679b94e7b91fc3c4f313e4 由此可见为假的Adobe Flash Player 的攻击样本 样本分析 通过五个函数,内部调用sub_40159D函数动态获取API函数 利用IDA python解密字符串。。 完整python代码 Python> idc.get_…

扫雷(蓝桥杯)

题目描述 小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下, 在一个二维平面上放置着 n 个炸雷,第 i 个炸雷 (xi , yi ,ri) 表示在坐标 (xi , yi) 处存在一个炸雷,它的爆炸范围是以半径为 ri 的一个圆。 为了顺利通过这片土…

Mac air 个人免费版VMWare Fusion安装及配置教程

Mac air 安装免费版VMWare Fusion教程及问题解决 1、下载VMWare Fusion2、下载wins镜像文件3、开始配置4、出现的问题及解决方法4.1 如何跳过启动时的网络连接4.2 启动后,无法连接网络怎么办4.3 怎么实现将文件拖拽到虚拟机中 当你手上是一台Mac电脑,却需…