【数据结构期末复习】完善中

文章目录

    • 二叉树的三种遍历方式
      • 怎么看遍历结果
      • 相关题目:已知一颗二叉树的后续遍历序列为:GFEDCBA;中序遍历序列为:FGAEBDC。画出这棵二叉树
        • 思路
        • 代码版
    • 先序线索树
    • 二叉树转树、或森林
      • 树转二叉树
      • 二叉树转树
      • 二叉树转森林
      • 森林转二叉树

二叉树的三种遍历方式

怎么看遍历结果

前中后序遍历,咱先看代码,方便理解

//先序遍历:Preorder Traversal
//中序遍历:Inorder Traversal
//后序遍历:Postorder Traversal
// 前序遍历
public static void preorderTraversal(TreeNode root) {
    if (root == null) {
        return;
    }
    // 访问根节点
    System.out.print(root.val + " ");
    // 递归遍历左子树
    preorderTraversal(root.left);
    // 递归遍历右子树
    preorderTraversal(root.right);
}

// 中序遍历
public static void inorderTraversal(TreeNode root) {
    if (root == null) {
        return;
    }
    // 递归遍历左子树
    inorderTraversal(root.left);
    // 访问根节点
    System.out.print(root.val + " ");
    // 递归遍历右子树
    inorderTraversal(root.right);
}

// 后序遍历
public static void postorderTraversal(TreeNode root) {
    if (root == null) {
        return;
    }
    // 递归遍历左子树
    postorderTraversal(root.left);
    // 递归遍历右子树
    postorderTraversal(root.right);
    // 访问根节点
    System.out.print(root.val + " ");
}

其实先中后说的都是打印“自己”的时机,先序遍历,就是先打印自己的值,然后再去左子树判断,再去右子树。最先打印的一定是头结点。
而中序遍历就是先打印左子树的值,再打印自己的,再去右子树看。
后序遍历,最后打印的是头结点。

二叉树三种遍历方式的参考图↓
二叉树三种遍历方式参考图

相关题目:已知一颗二叉树的后续遍历序列为:GFEDCBA;中序遍历序列为:FGAEBDC。画出这棵二叉树

思路
  1. 首先根据后序遍历的规律——最后打印的为头结点——A

  2. 找到A之后,再个根据中序遍历,将中序遍历的序列分为两组。A的左边为左子树,右边为右子树
    在这里插入图片描述

  3. 非标准思路:如果手写,到这一步,其实可以先尝试画左子树。尝试着画就行,画出来一个就按照给出的两种遍历序列,自己遍历遍历,看看结果不一样,一样了,就再画下一个结点,不一样了,就再改。

  4. 标准思路:递归建树。重复第2步的操作,把中序遍历的序列分为两组之后,[F,G],[E,B,D,C],后序遍历序列去掉已经画好的头结点A,[G,F,E,D,C,B]。再把←这个也分成两组[G,F],[E,D,C,B](分法其实还是看左子树的节点个数,A左边有两个,所以左子树有两个结点)

  5. 中序[F,G],后序[G,F],假如这也是一个二叉树的遍历结果,画出来它对应的树,你先画出来的不还是头结点F吗?F是后序最后一个,把它接在A的左孩子的位置。接着在去考虑G就好了。(我这里没画出来G,当是练习吧)
    在这里插入图片描述

  6. 中序[E,B,D,C],后序[E,D,C,B],这不直接老规矩了都?B是后序最后一个,直接连成A的右孩子。然后再分组就行了
    在这里插入图片描述

  7. 去掉已经画好的B,你看中序遍历B左边不就一个E吗?所以中序[E],[D,C],后序[E],[D,C]。
    在这里插入图片描述

  8. 对答案
    在这里插入图片描述

代码版
import java.util.HashMap;
import java.util.Map;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

public class BuildTree {
    public static TreeNode buildTree(int[] postorder, int[] inorder) {
        if (postorder == null || postorder.length == 0 || inorder == null || inorder.length == 0) {
            return null;
        }

        Map<Integer, Integer> postIndexMap = new HashMap<>();
        for (int i = 0; i < postorder.length; i++) {
            postIndexMap.put(postorder[i], i);
        }

        return buildTree(postorder, 0, postorder.length - 1, inorder, 0, inorder.length - 1, postIndexMap);
    }

    private static TreeNode buildTree(int[] postorder, int postStart, int postEnd, int[] inorder, int inStart, int inEnd, Map<Integer, Integer> postIndexMap) {
        if (postStart > postEnd || inStart > inEnd) {
            return null;
        }

        int rootVal = postorder[postEnd];
        TreeNode root = new TreeNode(rootVal);

        int rootIndex = postIndexMap.get(rootVal);
        // 计算左子树的节点个数
        int leftSize = searchElement(inorder,rootVal);
        // 递归构建左子树
        root.left = buildTree(postorder, postStart, rootIndex - 1, inorder, inStart, rootIndex - 1, postIndexMap);
        // 递归构建右子树
        root.right = buildTree(postorder, rootIndex + 1, postEnd - 1, inorder, rootIndex + 1, inEnd, postIndexMap);

        return root;
    }    
		//遍历方法可以从上边粘,过来就能用
    public static void main(String[] args) {
        // 后续遍历:4 5 2 6 7 3 1
        int[] postorder = {4, 5, 2, 6, 7, 3, 1};
        // 中序遍历:2 4 5 1 3 6 7
        int[] inorder = {2, 4, 5, 1, 3, 6, 7};

        TreeNode root = buildTree(postorder, inorder);
        System.out.println(root);
    }
    public static int searchElement(int[] array, int target) {
        int left = 0;
        int right = array.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (array[mid] == target) {
                return mid;
            } else if (array[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        // 元素未找到,返回 -1
        return -1;
    }
}

先序线索树

题目:根据先序遍历序列[A,F,G,B,E,C,D],线索化二叉树。
在这里插入图片描述

先序遍历序列:[A,F,G,B,E,C,D]
在先序遍历中,为了提高查找一个元素的前驱、后继的速度,有了线索化这个概念。
如何线索化:左孩子原来为空指前驱右孩子原来为空指后继不为空不看没前驱后继指到空

例:F的前驱是A,并且F的做指针原来指向空,所以现在指向A。而F原来右指针已经指向了G,不为空,不用考虑。
D左右指针原来都为空,D的前驱为C,所以做指针指向C,D没有后继,所以右指针还为空。

二叉树转树、或森林

树转二叉树

在这里插入图片描述
一棵树↑
横着,把自己的左孩子和它的兄弟给连起来
在这里插入图片描述
只连亲兄弟,F–G就别连了。
然后去掉“多余”的连线,再拉直。
多余的连线<A,C>,<A,D>,<B,F>
在这里插入图片描述

二叉树转树

把红色的这些节点(都是自己父节点的右孩子),“拉上去”
在这里插入图片描述
再补上蓝色的边,就是用父节点,连接自己左孩子的兄弟们
删除横这的边
在这里插入图片描述

二叉树转森林

在这里插入图片描述
把B和D拉上去,然后去掉横着的边(和转树其实挺像的,看头结点有没有右孩子吧,有了就转成森林了)
在这里插入图片描述

森林转二叉树

先把每一棵树都转成二叉树。转完之后头结点肯定没右孩子,有了,你就是没转对。
然后把后面的二叉树,当成第一棵树的右子树加进来
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
再把<D,C>连到B的右子树就行了

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

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

相关文章

Java之BigDecimal详解

一、BigDecimal概述 Java在java.math包中提供的API类BigDecimal&#xff0c;用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数&#xff0c;但在实际应用中&#xff0c;可能需要对更大或者更小的数进行运算和处理。一般情况下&#xff0c;对…

阿里云人工智能平台PAI多篇论文入选EMNLP 2023

近期&#xff0c;阿里云人工智能平台PAI主导的多篇论文在EMNLP2023上入选。EMNLP是人工智能自然语言处理领域的顶级国际会议&#xff0c;聚焦于自然语言处理技术在各个应用场景的学术研究&#xff0c;尤其重视自然语言处理的实证研究。该会议曾推动了预训练语言模型、文本挖掘、…

【基于卷积神经网络的疲劳检测与预警系统的设计与实现】

基于卷积神经网络的疲劳检测与预警系统的设计与实现 引言数据集介绍技术与工具1. OpenCV2. TensorFlow3. 卷积神经网络&#xff08;CNN&#xff09; 系统功能模块1. 视频采集模块2. 图像预处理模块3. 人脸识别模块4. 疲劳程度判别模块5. 报警模块 系统设计创新点1. 实时监测与预…

js解析.shp文件

效果图 原理与源码 本文采用的是shapefile.js工具 这里是他的npm地址 https://www.npmjs.com/package/shapefile 这是他的unpkg地址&#xff0c;可以点开查看源码 https://unpkg.com/shapefile0.6.6/dist/shapefile.js 这个最关键的核心问题是如何用这个工具&#xff0c;网上…

如何正确使用缓存来提升系统性能

文章目录 引言什么时候适合加缓存&#xff1f;示例1示例2&#xff1a;示例3&#xff1a; 缓存应该怎么配置&#xff1f;数据分布**缓存容量大小&#xff1a;**数据淘汰策略 缓存的副作用总结 引言 在上一篇文章IO密集型服务提升性能的三种方法中&#xff0c;我们提到了三种优化…

如何在iPad Pro上实现SSH远程连接服务器并进行云端编程开发【内网穿透】

文章目录 前言1. 在iPad下载Code APP2.安装cpolar内网穿透2.1 cpolar 安装2.2 创建TCP隧道 3. iPad远程vscode4. 配置固定TCP端口地址4.1 保留固定TCP地址4.2 配置固定的TCP端口地址4.3 使用固定TCP地址远程vscode 前言 本文主要介绍开源iPad应用IDE如何下载安装&#xff0c;并…

京微齐力:基于H7的平衡控制系统(一、姿态解析)

目录 前言一、关于平衡控制系统二、实验效果三、硬件选择1、H7P20N0L176-M2H12、MPU6050 四、理论简述五、程序设计1、Cordic算法2、MPU6050采集数据3、fir&iir滤波4、姿态解算 六、资源消耗&工程获取七、总结 前言 很久之前&#xff0c;就想用纯FPGA做一套控制系统。可…

9.2 Linux LED 驱动开发

一、Linux 下的 LED 驱动原理 Linux 下的任何驱动&#xff0c;最后都是要配置相应的硬件寄存器。 1. 地址映射 MMU 全称叫做 MemoryManage Unit&#xff0c;也就是内存管理单元。 现在的 Linux 支持无 MMU 处理器。MMU 主要完成的功能为&#xff1a; 1、完成虚拟空间到物理空间…

香港科技大学数据建模(MSc DDM)硕士学位项目(2024年秋季入学)招生宣讲会-四川大学专场

时间&#xff1a;2023 年 12 月 26 日&#xff08;周二&#xff09; 14:30 地点&#xff1a;四川大学望江校区基础教学楼 C 座 102 嘉宾教授&#xff1a;潘鼎 教授 项目旨在培养科学或工程背景的学员从数据中提取信息的数据建模能力&#xff0c;训练其拥有优秀的解难和逻辑思…

旅游景区文旅地产如何通过数字人开启数字营销?

随着元宇宙的发展&#xff0c;为虚实相生的营销带来更多的可能性。基于虚拟世界对于现实世界的模仿&#xff0c;通过构建沉浸式数字体验&#xff0c;增强现实生活的数字体验&#xff0c;强调实现真实体验的数字化&#xff0c;让品牌结合数字人开启数字化营销。 *图片源于网络 …

谷歌浏览器怎么关闭自动更新?

文章目录 一、方式一 谷歌浏览器安装完成后&#xff0c;每天都会自动更新到最新的版本&#xff0c;但是对于有些程序的驱动&#xff0c;浏览器一更新就不能自动启动浏览器&#xff0c;会给我们带来很多困扰。下面我们介绍怎么将谷歌浏览器自动更新关闭&#xff0c;如果需要更新…

# 和 $ 的区别②

上节博客说了使用 # 的时候,如果参数为 String ,会自动加上单引号 但是当参数为String 类型的时候,也有不需要加单引号的情况,这时候用 # 那就会出问题 比如根据 升序(asc) 或者 降序(desc) 查找的时候,加了单引号那就会报错 这个时候我们就只能使用 $ 如果看不懂代码,就去…

Android Studio实现俄罗斯方块

文章目录 一、项目概述二、开发环境三、详细设计3.1 CacheUtils类3.2 BlockAdapter类3.3 CommonAdapter类3.4 SelectActivity3.5 MainActivity 四、运行演示五、项目总结 一、项目概述 俄罗斯方块是一种经典的电子游戏&#xff0c;最早由俄罗斯人Alexey Pajitnov在1984年创建。…

Rask AI引领革新,推出多扬声器口型同步技术,打造本地化内容新纪元

“ Rask AI是一个先进的AI驱动视频和音频本地化工具&#xff0c;旨在帮助内容创作者和公司快速、高效地将他们的视频转换成60多种语言。通过不断创新和改进产品功能&#xff0c;Rask AI正塑造着未来媒体产业的发展趋势。 ” 在多语种内容创作的新时代&#xff0c;Rask AI不断突…

spring 笔记六 SpringMVC 获得请求数据

文章目录 SpringMVC 获得请求数据获得请求参数获得基本类型参数获得POJO类型参数获得数组类型参数获得集合类型参数请求数据乱码问题参数绑定注解requestParam获得Restful风格的参数获得Restful风格的参数自定义类型转换器获得Servlet相关API获得请求头RequestHeaderCookieValu…

CMS—评论设计

一、需求分析 1.1、常见行为 1.敏感词过滤 2.新增评论&#xff08;作品下、评论下&#xff09; 3.删除评论&#xff08;作品作者、上级评论者、本级作者&#xff09; 4.上级评论删除关联下级评论 5.逻辑状态变更&#xff08;上线、下线、废弃...&#xff09; 6.上逻辑状态变更…

Mac部署Odoo环境-Odoo本地环境部署

Odoo本地环境部署 安装Python安装Homebrew安装依赖brew install libxmlsec1 Python运行环境Pycharm示例配置 Mac部署Odoo环境-Odoo本地环境部署 安装Python 新机&#xff0c;若系统没有预装Python&#xff0c;则安装需要版本的Python 点击查询Python官网下载 安装Homebrew 一…

solidity 特性导致的漏洞

目录 1、默认可见性 2、浮点数精度缺失 3、错误的构造函数 4、自毁函数 5、未初始化指针-状态变量覆盖 1、默认可见性 Solidity 的函数和状态变量有四种可见性&#xff1a;external、public、internal、private。函数可见性默认为 public&#xff0c;状态变量可见性默认为…

RS485转WiFi工业路由器在冷链物流温度监控中的应用

随着物联网技术的不断发展和应用&#xff0c;冷链物流行业也迎来了新的机遇和挑战。在冷链物流中&#xff0c;对温度监控的要求尤为重要&#xff0c;因为温度是保证货物质量和安全的关键因素之一。而RS485转WiFi工业路由器则成为了实现高效、可靠的温度监控系统的重要组成部分。…

Linux ed命令教程:如何使用ed命令编辑文本文件(附案例详解和注意事项)

Linux ed命令介绍 ed命令是Linux中的一个简单文本编辑器。它是一种基于行的文本编辑器&#xff0c;用于创建、修改和操作文本文件。它是Unix中最早的编辑器&#xff0c;后来被vi和emacs文本编辑器所取代。 Linux ed命令适用的Linux版本 ed命令在大多数Linux发行版中都可以使…