【二叉树】遍历及构造

1. 定义

二叉树是一种树形数据结构,由节点组成,每个节点最多有两个子节点,分别为左子节点和右子节点。二叉树具有以下性质:
每个节点最多有两个子节点,称为左子节点和右子节点。

  1. 左子节点和右子节点可以为空,即一个节点没有子节点或只有一个子节点。
  2. 二叉树的子树也是二叉树,即每个子节点都可以看作是根节点,构成一个新的二叉树。
  3. 二叉树可以是空树,即不包含任何节点的情况。
  4. 二叉树的节点之间不存在环,即不能通过任意路径从一个节点回到自身。

2. 遍历

二叉树的遍历主要有三种方式,前序遍历、中序遍历和后序遍历。

  1. 前序遍历是根据【根-左-右】的顺序进行遍历,即首先访问根节点,然后访问左子树,最后访问右子树。
  2. 中序遍历是根据【左-根-右】的顺序进行遍历,即首先访问左子树,然后访问根节点,最后访问右子树。
  3. 后序遍历是根据【左-右-根】的顺序进行遍历,首先访问左子树,然后访问右子树,最后访问根节点。

3. 节点结构定义

构建二叉树,首先要构造二叉树的节点,以下是二叉树节点的定义:

public class TreeNode {int val;        // 节点的值TreeNode left;  // 左子节点TreeNode right; // 右子节点// 无参构造方法TreeNode() {}// 含值的构造方法TreeNode(int val) { this.val = val; }// 含值、左子节点和右子节点的构造方法TreeNode(int val, TreeNode left, TreeNode right) {this.val = val;this.left = left;this.right = right;}
}

在上述代码中,我们定义了一个名为TreeNode的类,包含了节点的值(val)、左子节点(left)、右子节点(right)三个成员变量。同时,我们提供了三个构造方法,分别用于创建空节点、只含值的节点和含值、左右子节点的节点。

4. 通过遍历结果生成二叉树

前提无重复值

1. 已知前中序遍历生成二叉树 力扣105

  1. 常用递归写法
    将问题拆分为一个个子问题,即将每个二叉树结点当作一个子问题来求解。
public TreeNode buildTree(int[] preorder, int[] inorder) {int n = preorder.length;if(n == 0){return null;}int leftSize = indexOf(inorder,preorder[0]);int[] pre1 = Arrays.copyOfRange(preorder,1,1+leftSize);int[] pre2 = Arrays.copyOfRange(preorder,1+leftSize,n);int[] in1 = Arrays.copyOfRange(inorder,0,leftSize);int[] in2 = Arrays.copyOfRange(inorder,leftSize+1,n);TreeNode left = buildTree(pre1,in1);TreeNode right = buildTree(pre2,in2);return new TreeNode(preorder[0],left,right);
}
public int indexOf(int[] inorder,int x){for(int i = 0;i < inorder.length;i++){if(inorder[i] == x){return i;}}return -1;
}

时间复杂度:O(n^2),空间复杂度: O(n^2)
2. 在上述方法需要遍历整个集合求出根结点的下标,时间复杂度为O(n),可以使用哈希表来进一步简化这一过程:

public TreeNode buildTree(int[] preorder,int[] inorder){int n = preorder.length;Map<Integer,Integer> index = new HashMap<Integer,Integer>();for(int i =  0;i < n;i++){index.put(inorder[i],i);}return dfs(preorder,0,n,inorder,0,n,index);}public TreeNode dfs(int[] preorder,int preL,int preR,int[] inorder,int inL,int inR,Map<Integer,Integer> index){if(preL == preR){return null;}int leftSize = index.get(preorder[preL]) - inL;TreeNode left = dfs(preorder,preL + 1,preL + 1 + leftSize,inorder,inL,inL+leftSize,index);TreeNode right = dfs(preorder,preL + 1 + leftSize,preR,inorder,inL+leftSize + 1,inR,index);return new TreeNode(preorder[preL],left,right);} 

时间复杂度:O(n),空间复杂度:O(n)

2. 已知中后序遍历生成二叉树 力扣106

  1. 常用递归写法
    首先要确定左子树的长度,然后根据中后序遍历的特点进行节点划分。
public TreeNode buildTree(int[] inorder, int[] postorder) {int n = inorder.length;if(n == 0){return null;}int leftSize = indexOf(inorder,postorder[n - 1]);int[] inL = Arrays.copyOfRange(inorder,0,leftSize);int[] inR = Arrays.copyOfRange(inorder,leftSize + 1,n);int[] postL = Arrays.copyOfRange(postorder,0,leftSize);int[] postR = Arrays.copyOfRange(postorder,leftSize,n - 1);TreeNode left =buildTree(inL,postL);TreeNode right = buildTree(inR,postR);return new TreeNode(postorder[n-1],left,right);}public int indexOf(int[] arr,int x){int n = arr.length;for(int i =0;i < n;i++){if(arr[i] == x){return i;}}return -1;}

时间复杂度:O(n^2),空间复杂度: O(n^2)
3. 使用哈希表来进一步简化:

public TreeNode buildTree(int[] inorder, int[] postorder) {int n = inorder.length;HashMap<Integer,Integer> index = new HashMap<Integer,Integer>();for(int i = 0;i < n;i++){index.put(inorder[i],i);}return dfs(inorder,0,n-1,postorder,0,n-1,index);}public TreeNode dfs(int[] inorder,int inL,int inR,int[] postorder,int postL,int postR,HashMap<Integer,Integer> index){if(inL > inR){return null;}if(inL == inR){return new TreeNode(inorder[inL]);}int leftSize = index.get(postorder[postR]) - inL;TreeNode left = dfs(inorder,inL,inL + leftSize - 1,postorder,postL,postL + leftSize - 1,index);TreeNode right = dfs(inorder,inL + leftSize + 1,inR,postorder,postL + leftSize,postR - 1,index);return new TreeNode(postorder[postR],left,right);}

时间复杂度:O(n),空间复杂度:O(n)

2. 已知前后序遍历生成二叉树 力扣889

  1. 常用递归写法
public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {int n = preorder.length;if(n == 0){return null;}if(n == 1){return new TreeNode(preorder[0]);}int leftSize = indexOf(postorder,preorder[1]) + 1;int[] preL = Arrays.copyOfRange(preorder,1,leftSize + 1);int[] preR = Arrays.copyOfRange(preorder,leftSize + 1,n);int[] postL = Arrays.copyOfRange(postorder,0,leftSize);int[] postR = Arrays.copyOfRange(postorder,leftSize,n-1);TreeNode left = constructFromPrePost(preL,postL);TreeNode right = constructFromPrePost(preR,postR);return new TreeNode(preorder[0],left,right);}public int indexOf(int[] arr,int x){int n = arr.length;for(int i  =0; i< n;i++){if(arr[i] == x){return i;}}return -1;}

时间复杂度:O(n^2),空间复杂度: O(n^2)
2. 使用哈希表来进一步简化:

public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {int n = preorder.length;HashMap<Integer,Integer> index = new HashMap<Integer,Integer>();for(int i  =0;i < n;i++){index.put(postorder[i],i);}return dfs(preorder,0,n-1,postorder,0,n-1,index);}public TreeNode dfs(int[] preorder,int preL,int preR,int[] postorder,int postL,int postR,HashMap<Integer,Integer> index){if(preL > preR)return null;if(preL == preR)return new TreeNode(preorder[preL]);int leftSize = index.get(preorder[preL + 1]) - postL + 1;TreeNode left = dfs(preorder,preL + 1,preL + leftSize,postorder,postL,postL + leftSize - 1,index);TreeNode right = dfs(preorder,preL + leftSize + 1,preR,postorder,postL + leftSize,postR - 1,index);return new TreeNode(preorder[preL],left,right);}

时间复杂度:O(n),空间复杂度:O(n)

5. 总结

通过前中、前后、中后遍历结果生成二叉树关键点在于确定左子树和右子树的边缘范围。

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

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

相关文章

命令执行讲解和函数

命令执行漏洞简介 命令执行漏洞产生原因 应用未对用户输入做严格得检查过滤&#xff0c;导致用户输入得参数被当成命令来执行 命令执行漏洞的危害 1.继承Web服务程序的权限去执行系统命会或读写文件 2.反弹shell&#xff0c;获得目标服务器的权限 3.进一步内网渗透 远程代…

泛微e-office系统存在敏感信息泄露 附POC软件

免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 泛微e-office系统简介 微信公众号搜索:南风漏洞复…

mysql 锁详解

目录 前言 一、全局锁 二、表级锁 三、行锁 前言 为什么要设计锁&#xff0c;锁设计初衷是为了解决多线程下并发问题。出现并发的时候用锁进行数据同步&#xff0c;避免因并发造成了数据错误(数据覆盖)。可见锁的重要性&#xff0c;并不是所有的数据库都有锁。比如Redis&a…

什么是CODESYS开发系统

CODESYS是一种用于工业自动化领域的开发系统软件&#xff0c;提供了一个完整集成的开发环境。该软件由德国CODESYS GmbH&#xff08;原 3S-Smart Software Solutions GmbH&#xff09;公司开发&#xff0c;其最新版本为CODESYS V3。 CODESYS开发系统具有多种特性和优点。首先&a…

⭐北邮复试刷题105. 从前序与中序遍历序列构造二叉树__递归分治 (力扣每日一题)

105. 从前序与中序遍历序列构造二叉树 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,…

Rocky 8.9 Kubespray v2.24.0 在线部署 kubernetes v1.28.6 集群

文章目录 1. 简介2. 预备条件3. 基础配置3.1 配置hostname3.2 配置互信 4. 配置部署环境4.1 在线安装docker4.2 启动容器 kubespray4.3 编写 inventory.ini4.4 关闭防火墙、swap、selinux4.5 配置内核模块 5. 部署6. 集群检查 1. 简介 kubespray​ 是一个用于部署和管理 Kuber…

抽象方法与设计模式

抽象方法与设计模式 设计模式的六大原则工厂模式单例模式建造者模式过滤器模式装饰器模式享元模式责任链模式模板模式 真正的屎山不是初级程序员写的巨量胶水代码&#xff0c;而是没学明白抽象的程序员写的大量设计模式耦合形成的。你甚至不理解为什么当初的创作者需要使用到这…

基于postMessage和BroadcastChannel实现浏览器跨Tab窗口通信的方法介绍

文章目录 一、Broadcast Channel1、创建实例2、监听消息3、发送消息4、关闭5、示例演示5.1、主控页面5.2、受控页面 二、postMessage1、语法1.1、targetWindow1.2、message1.3、targetOrigin1.4、transfer&#xff08;可选的&#xff09; 2、示例演示2.1、parent页面2.2、child…

Elsevier投稿录用后的一些疑问

在elsevier投稿被录用之后&#xff0c;会收到好几个邮件&#xff1a; 第一封邮件是给你一个在线修改稿子的网站&#xff0c;让你核实作者&#xff0c;文献等等的信息&#xff0c;以及编辑做的修改&#xff0c;要注意的是有几个query问题是必须回答的。然后你在线修改完提交就可…

CF1468J Road Reform 题解

CF1468J Road Reform 题解 link CF1468J Road Reform 题面翻译 给定一个有 n n n 个节点&#xff0c; m m m 条无向带权边的图&#xff0c;和一个参数 k k k&#xff0c;第 i i i 条边权值为 s i s_i si​。 现在你要保留这个图中的 n − 1 n-1 n−1 条边使得这个图变…

java导出动态下拉框excel模板

1.原始模板 2.导出模板,下拉框为数据库中得到动态数据 public void downloadTemplate(HttpServletResponse response) throws IOException {// 所有部门List<String, String> departments expertManageMapper.selectAllDepartment();//所有职位List<String, String&g…

前端关于Vue跳转外部链接(百度为例)

一定要加这句 window.location.href http://www.baidu.com/s?wd this.wd;关于Vue跳转外部链接&#xff08;百度为例&#xff09;_vue3.2 点击按钮 router.resolve 跳转 百度-CSDN博客 <img src"./hd1.jpg" width"200px" height"100px" c…

模块 time:时间和日期处理

MicroPython内置模块 time&#xff1a;时间和日期处理 MicroPython的内置模块time是一个用于处理时间相关功能的模块&#xff0c;它实现了CPython模块的一个子集&#xff0c;但也有一些特殊的特点和限制。本文将从以下几个方面介绍time模块的主要特点、应用场景&#xff0c;以…

基于Java (spring-boot)的社区物业管理系统

一、项目介绍 本系统共分为两个角色&#xff1a;管理员和业主。 主要功能有&#xff0c;核心业务处理&#xff0c;基础信息管理&#xff0c;数据统计分析 核心业务处理&#xff1a;车位收费管理&#xff0c;物业收费管理&#xff0c;投诉信息管理&#xff0c;保修信息管理。 …

Top-N 泛型工具类

一、代码实现 public class TopNUtil<E extends Comparable<E>> {private final PriorityQueue<E> priorityQueue;private final int n;/*** 构造 Top-N*/public TopNUtil(int size) {if (size < 0) {throw new IllegalArgumentException("Top-N si…

嵌入式学习day22 Linux

文件IO: 1. lseek off_t lseek(int fd, off_t offset, int whence); 功能: 重新设定文件描述符的偏移量 参数: fd:文件描述符 offset:偏移量 whence: SEEK_SET 文件开头 …

代码随想录三刷day04

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣209. 长度最小的子数组二、力扣904. 水果成篮三、力扣76. 最小覆盖子串 前言 接下来就开始介绍数组操作中另一个重要的方法&#xff1a;滑动窗口。 所谓…

C++从入门到精通 第十四章(STL容器)【下】

七、list容器 1、list的基本概念 &#xff08;1&#xff09;list的功能是将数据进行链式存储&#xff0c;对应数据结构中的链表&#xff0c;链表是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的。 &#xff08;2&#xff…

《VitePress 简易速速上手小册》第2章:Markdown 与页面创建(2024 最新版)

文章目录 2.1 Markdown 基础及扩展2.1.1 基础知识点解析2.1.2 重点案例&#xff1a;技术博客2.1.3 拓展案例 1&#xff1a;食谱分享2.1.4 拓展案例 2&#xff1a;个人旅行日记 2.2 页面结构与布局设计2.2.1 基础知识点解析2.2.2 重点案例&#xff1a;公司官网2.2.3 拓展案例 1&…

Linux系统运维:性能监视和分析工具sar命令详解

目 录 一、sar工具介绍 二、sar工作原理 &#xff08;一&#xff09;原理概述 &#xff08;二&#xff09;sar数据收集器 三、sar命令语法 四、sar主要功能介绍 &#xff08;一&#xff09;功能概述 &#xff08;二&#xff09;CPU统计数据 &#xff08;三&a…