当前位置: 首页 > news >正文

LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解

LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解

文章目录

  • 二叉树遍历
    • 题目描述
    • 解题思路与代码
      • 递归遍历
      • 迭代遍历
      • 层序遍历
    • 线索二叉树:

二叉树遍历

题目描述

从根节点往下查找,先找左子树、直至左子树为空(左子节点逐个入栈、直至左子节点为空),再找右子树(出栈找右子节点)
前序遍历:根左右,第一次经过节点即打印,直到打印null,往回溯,打印右子树
中序遍历:左根右,第二次经过该节点时进行打印,即左边回溯时
后序遍历:左右根,第三次经过该节点时进行打印,即右边回溯时
层序遍历:按照层级,从上往下,从左到右。使用广度优先搜索算法。
从根节点往下查找,先找左子树、直至左子树为空(左子节点逐个入栈、直至左子节点为空),再找右子树(出栈找右子节点)

解题思路与代码

递归遍历

    public static void preorder(TreeNode root) {if (root == null) {return;}//System.out.println(root.val);//前序 第一次成为栈顶preorder(root.left);System.out.println(root.val);//中序 第二次成为栈顶preorder(root.right);//System.out.println(root.val);//后序 第三次成为栈顶}

迭代遍历

    //前序:使用stack记录递归路径,左子节点后添加保证先出栈public static void preOrder2(TreeNode head) {if (head != null) {Stack<TreeNode> stack = new Stack<TreeNode>();stack.add(head);while (!stack.isEmpty()) {head = stack.pop();if(head != null){System.out.println(head.val);stack.push(head.right);stack.push(head.left);}}}}//中序:将左子节点入栈,出栈打印值,然后添加右子节点public static void preOrder3(TreeNode head) {if (head != null) {Stack<TreeNode> stack = new Stack<TreeNode>();while (!stack.isEmpty() || head != null) {if (head != null) {stack.push(head);head = head.left;} else {head = stack.pop();System.out.println(head.val);head = head.right;}}}}//后序:public static void postorderTraversal(TreeNode root) {if (root == null) {return ;}Deque<TreeNode> stack = new LinkedList<TreeNode>();TreeNode prev = null;while (root != null || !stack.isEmpty()) {while (root != null) {stack.push(root);root = root.left;}root = stack.pop();//root的左子节点为nullif (root.right == null || root.right == prev) {//右子节点为null,或者右子节点已打印System.out.println(root.val);prev = root;root = null;} else {//右子节点有值,重新入栈stack.push(root);root = root.right;}}}

层序遍历

   public static void levelTraversal(Node root) {Queue<Node> q = new LinkedList<>();q.add(root);while (!q.isEmpty()) {Node temp = q.poll();if (temp != null) {System.out.print(temp.value + " ");q.add(temp.left);q.add(temp.right);}}}public static void deepOrder(TreeNode root) {if (root == null) {return ;}Queue<TreeNode> queue = new LinkedList<TreeNode>();queue.offer(root);while (!queue.isEmpty()) {for (int i = 1; i <= queue.size(); ++i) {TreeNode node = queue.poll();System.out.println(node.val);if (node.left != null) {queue.offer(node.left);}if (node.right != null) {queue.offer(node.right);}}}}private static List order(TreeNode root, int i, ArrayList list) {if (root == null) {return null;}int length = list.size();if(length <= i){for(int j=0; j<= i-length; j++){list.add(length+j,null);}}list.set(i,root.val);order(root.left, 2 * i,list);order(root.right, 2 * i + 1,list);return list;}

线索二叉树:

在N个节点的二叉树中,每个节点有2个指针,所以一共有2N个指针,除了根节点以外,每一个节点都有一个指针从它的父节点指向它,所以一共使用了N-1个指针,所以剩下2N-(N-1)也就是N+1个空指针;

如果能利用这些空指针域来存放指向该节点的直接前驱或是直接后继的指针,则可由此信息直接找到在该遍历次序下的前驱节点或后继节点,从而比递归遍历提高了遍历速度,节省了建立系统递归栈所使用的存储空间;

这些被重新利用起来的空指针就被称为线索(Thread),加上了线索的二叉树就是线索二叉树实现思路:按某种次序遍历二叉树,在遍历过程中用线索取代空指针即可。以中序遍历为例,首先找到中序遍历的开始节点,然后利用线索依次查找后继节点即可。

由于它充分利用了空指针域的空间(等于节省了空间),又保证了创建时的一次遍历就可以终生受用前驱、后继的信息(这意味着节省了时间),所以在实际问题中,如果所使用的二叉树需要经常遍历或查找节点时需要某种遍历中的前驱和后继,那么采用线索二叉链表的存储结构就是不错的选择morris遍历:构建中序线索二叉树的过程中,如果发现前驱节点的右指针指向自身,则将指针(线索)删除

public static void morrisPre(Node cur) {if(head == null){return;}Node mostRight = null;while (cur != null){// cur表示当前节点,mostRight表示cur的左孩子的最右节点mostRight = cur.left;if(mostRight != null){// cur有左孩子,找到cur左子树最右节点while (mostRight.right !=null && mostRight.right != cur){mostRight = mostRight.right;}// mostRight的右孩子指向空,让其指向cur,cur向左移动if(mostRight.right == null){mostRight.right = cur;System.out.print(cur.value+" ");cur = cur.left;continue;}else {// mostRight的右孩子指向cur,让其指向空,cur向右移动mostRight.right = null;}}else {System.out.print(cur.value + " ");}cur = cur.right;}}public static void morrisIn(Node cur) {if(head == null){return;}Node mostRight = null;while (cur != null){mostRight = cur.left;if(mostRight != null){while (mostRight.right !=null && mostRight.right != cur){mostRight = mostRight.right;}if(mostRight.right == null){mostRight.right = cur;cur = cur.left;continue;}else {mostRight.right = null;}}System.out.print(cur.value+" ");cur = cur.right;}}public static void morrisPos(TreeNode cur) {if (cur == null) {return;}TreeNode head = cur;TreeNode mostRight = null;while (cur != null) {mostRight = cur.left;if (mostRight != null) {while (mostRight.right != null && mostRight.right != cur) {mostRight = mostRight.right;}if (mostRight.right == null) {mostRight.right = cur;cur = cur.left;continue;} else {mostRight.right = null;printEdge(cur.left);}}cur = cur.right;}printEdge(head);System.out.println();}public static void printEdge(TreeNode head) {TreeNode tail = reverseEdge(head);TreeNode cur = tail;while (cur != null) {System.out.print(cur.val + " ");cur = cur.right;}reverseEdge(tail);}public static TreeNode reverseEdge(TreeNode from) {TreeNode pre = null;TreeNode next = null;while (from != null) {next = from.rightfrom.right = pre;pre = from;from = next;}return pre;}public List<Integer> postorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<Integer>();if (root == null) {return res;}Deque<TreeNode> stack = new LinkedList<TreeNode>();TreeNode prev = null;while (root != null || !stack.isEmpty()) {while (root != null) {stack.push(root);root = root.left;}root = stack.pop();if (root.right == null || root.right == prev) {res.add(root.val);prev = root;root = null;} else {stack.push(root);root = root.right;}}return res;}

相关文章:

LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解

LeetCode经典算法题&#xff1a;二叉树遍历&#xff08;递归遍历迭代遍历层序遍历&#xff09;以及线索二叉树java详解 文章目录二叉树遍历题目描述解题思路与代码递归遍历迭代遍历层序遍历线索二叉树&#xff1a;二叉树遍历 题目描述 从根节点往下查找&#xff0c;先找左子树…...

【Java闭关修炼】MyBatis-接口代理的方式实现Dao层

【Java闭关修炼】MyBatis-接口代理的方式实现Dao层实现规则代码实现代理对象分析接口代理方式小结实现规则 映射配置文件中的名称空间必须和Dao层接口的全类名相同映射配置文件的增删改查标签的id属性必须和Dao层接口方法的参数相同映射配置文件中的增删改查标签的parameterTyp…...

2022年网络安全政策态势分析与2023年立法趋势

近日&#xff0c;公安部第三研究所网络安全法律研究中心与 360 集团法务中心联合共同发布了《全球网络安全政策法律发展年度报告&#xff08;2022&#xff09;》。《报告》概览2022年全球网络安全形势与政策法律态势&#xff0c;并对2023年及后续短期内网络安全政策、立法趋势进…...

使用vmware制作云平台redhat7.9镜像模板

一、概述 1.1 redhat7.9 定制镜像上传到云平台。 这个制作镜像得方式适用于多种iso 镜像。 将iso 镜像通过vmware 创建出一台虚机&#xff0c;对虚机做一些基础配置。在虚机上安装kvm 虚拟化得工具&#xff0c; 将iso 镜像在导入虚机种通过kvm创建一下虚机&#xff0c; 虚机创…...

OpenCV基础(28)使用OpenCV进行摄像机标定Python和C++

摄像头是机器人、监控、太空探索、社交媒体、工业自动化甚至娱乐业等多个领域不可或缺的一部分。 对于许多应用&#xff0c;必须了解相机的参数才能有效地将其用作视觉传感器。 在这篇文章中&#xff0c;您将了解相机校准所涉及的步骤及其意义。 我们还共享 C 和 Python 代码以…...

APB总线详解及手撕代码

本文的参考资料为官方文档AMBA™3 APB Protocol specification文档下载地址&#xff1a; https://pan.baidu.com/s/1Vsj4RdyCLan6jE-quAsEuw?pwdw5bi 提取码&#xff1a;w5bi APB端口介绍介绍总线具体握手规则之前&#xff0c;需要先熟悉一下APB总线端口&#xff0c;APB的端口…...

【Linux/Windows】源文件乱码问题解决方法总结

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;Linux技术&…...

Python 四大主流 Web 编程框架

目前Python的网络编程框架已经多达几十个&#xff0c;逐个学习它们显然不现实。但这些框架在系统架构和运行环境中有很多共通之处&#xff0c;本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Python网络框架&#xff1a;Django、Tornado、Flask、Twisted。 …...

学UI设计,可以向哪些方向发展?该怎么学?

1、什么是UI设计&#xff1f;UI设计&#xff0c;全称 User Interface&#xff0c;翻译成中文意思叫做用户界面设计。2、UI设计的类型UI设计按用户和界面来分可分成四种UI设计。分别是移动端UI设计&#xff0c;PC端UI设计&#xff0c;游戏UI设计&#xff0c;以及其它UI设计。第一…...

【C++】初识CC++内存管理

前言 我们都知道C&C是非常注重性能的语言&#xff0c;因此对于C&C的内存管理是每一个C/C学习者必须重点掌握的内容&#xff0c;本章我们并不是深入讲解C&C内存管理&#xff0c;而是介绍C&C内存管理的基础知识&#xff0c;为我们以后深入理解C&C内存管理做铺…...

Nacos快速使用指南

简单例子&#xff1a;springboot快速集成nacos官方github文档命名空间是绝对隔离的。group之间可以通过配置实现跨 group访问配置中心Nacos config官方文档应用级别的默认配置文件名&#xff08;dataId&#xff09;dataId 的完整格式如下&#xff1a;${prefix}-${spring.profil…...

复旦发布国内首个类ChatGPT模型MOSS,和《流浪地球》有关?

昨晚&#xff0c;复旦大学自然语言处理实验室邱锡鹏教授团队发布国内首个类ChatGPT模型MOSS&#xff0c;现已发布至公开平台https://moss.fastnlp.top/ &#xff0c;邀公众参与内测。 MOSS和ChatGPT一样&#xff0c;开发的过程也包括自然语言模型的基座训练、理解人类意图的对…...

国家级高新区企业主要经济指标(2012-2021年)

数据来源&#xff1a;国家统计局 时间跨度&#xff1a;2012-2021 区域范围&#xff1a;全国&#xff08;及各分类统计指标&#xff09; 指标说明&#xff1a;手工提取最新的中国统计年鉴数据中各个excel指标表&#xff0c;形成各个指标文件的多年度数据&#xff0c;便于多年…...

SpringBoot2核心技术-核心功能【05、Web开发】

目录 1、SpringMVC自动配置概览 2、简单功能分析 2.1、静态资源访问 1、静态资源目录 2、静态资源访问前缀 2.2、欢迎页支持 2.3、自定义 Favicon 2.4、静态资源配置原理 3、请求参数处理 0、请求映射 1、rest使用与原理 2、请求映射原理 1、普通参数与基本注解 …...

2021-03 青少年软件编程(C语言)等级考试试卷(六级)解析

2021-03 青少年软件编程(C语言)等级考试试卷(六级)解析T1. 生日相同 2.0 在一个有180人的大班级中,存在两个人生日相同的概率非常大,现给出每个学生的名字,出生月日。试找出所有生日相同的学生。 时间限制:1000 内存限制:65536 输入 第一行为整数n,表示有n个学生,n …...

数据库的多租户隔离

数据库的多租户隔离有三种方案 1、独立数据库 一个租户一个数据库&#xff0c;这种方案的用户数据隔离级别最高&#xff0c;安全性最好&#xff0c;成本也最高 优点&#xff1a;为不同的租户提供独立的数据库&#xff0c;有助于简化数据模型的扩展设计&#xff0c;满足不同租…...

网络输入分辨率是否越大越好

目标检测比如 yolov5&#xff0c;训练输入图像大小默认是 640*640&#xff0c;这个是不是越大训练的效果越好 &#xff1f; 这个肯定不是的。而且&#xff0c;如果仅调整输入图像的分辨率&#xff0c;不改变网络结构的话&#xff0c;检测准确率反而会下降的。首先&#xff0c;…...

离线采集普遍解决方案

简介 使用Datax每日全量相关全量表&#xff0c;使用Maxwell增量采集到Kafka然后到Flume然后到Hdfs。 DataX全量 生成模板Json gen_import_config.py # codingutf-8 import json import getopt import os import sys import MySQLdb#MySQL相关配置&#xff0c;需根据实际情…...

SAP ABAP 数据类型P类型详解

ABAP中比较难以理解的是P类型的使用&#xff0c;P类型是一种压缩类型&#xff0c;主要用于存储小数&#xff0c;定义时要指定字节数和小数点位数&#xff0c;定义语法如下&#xff1a; DATA: name(n) TYPE P decimals m,n代表字节数&#xff0c;最大为16&#xff0c;m是小…...

应用沙盒seccomp的使用

应用沙盒原理参考https://zhuanlan.zhihu.com/p/513688516 1、什么是Seccomp? seccomp 是 secure computing 的缩写,其是 Linux kernel 从2.6.23版本引入的一种简洁的 sandboxing 机制。 系统调用: 在Linux中,将程序的运行空间分为内核与用户空间(内核态和用户态),在逻辑…...

C++项目——高并发内存池(2)——thread_cache的基础功能实现

1.并发内存池concurrent memory pool 组成部分 thread cache、central cache、page cache thread cache&#xff1a;线程缓存是每个线程独有的&#xff0c;用于小于64k的内存的分配&#xff0c;线程从这里申请内存不需要加锁&#xff0c;每个线程独享一个cache&#xff0c;这…...

【C进阶】数据的存储

文章目录:star:1. 数据类型:star:2. 整形在内存中的存储2.1 存储规则2.2 存储模式2.3 验证大小端模式:star:3. 数据范围3.1 整形溢出3.2 数据范围的求解3.3 练习:star:4. 浮点型在内存中的存储4.1 浮点数的存储规则4.2 练习5. :star::star:总结(思维导图)⭐️1. 数据类型 在了…...

【已解决】异常断电文件损坏clickhouse启动不了:filesystem error Structure needs cleaning

问题 办公室有一台二手服务器&#xff0c;作为平时开发测试使用。由于机器没放在机房&#xff0c;会偶发断电异常断电后&#xff0c;文件系统是有出问题的可能的&#xff0c;尤其是一些不断在读写合并的文件春节后&#xff0c;发现clickhouse启动不了&#xff0c;使用systemct…...

FlinkSQL行级权限解决方案及源码

FlinkSQL的行级权限解决方案及源码&#xff0c;支持面向用户级别的行级数据访问控制&#xff0c;即特定用户只能访问授权过的行&#xff0c;隐藏未授权的行数据。此方案是实时领域Flink的解决方案&#xff0c;类似离线数仓Hive中Ranger Row-level Filter方案。 源码地址: https…...

【基础篇】8 # 递归:如何避免出现堆栈溢出呢?

说明 【数据结构与算法之美】专栏学习笔记 什么是递归&#xff1f; 递归是一种应用非常广泛的算法&#xff08;或者编程技巧&#xff09;&#xff0c;比如 DFS 深度优先搜索、前中后序二叉树遍历等等都是用到了递归。 方法或函数调用自身的方式称为递归调用&#xff0c;调用…...

基于微信公众号(服务号)实现扫码自动登录系统功能

微信提供了两种方法都可以实现扫描登录。 一种是基于微信公众平台的扫码登录&#xff0c;另一种是基于微信开放平台的扫码登录。 两者的区别: 微信开放平台需要企业认证才能注册&#xff08;认证费用300元&#xff0c;只需要认证1次&#xff0c;后续不再需要进行缴费年审&#…...

AXI实战(二)-跟着产品手册设计AXI-Lite外设(AXI-Lite转串口实现)

AXI实战(二)-跟着产品手册设计AXI-Lite 设(AXI-Lite转串口实现) 看完在本文后,你将可能拥有: 一个AXI_Lite转串口的从端(Slave)设计使用SV仿真AXI-Lite总线的完整体验实现如何在读通道中实现"等待"小何的AXI实战系列开更了,以下是初定的大纲安排: 欢迎感兴趣的…...

一周搞定模拟电路视频教程,拒绝讲PPT,仿真软件配合教学,真正一周搞定

目录1、灵魂拷问2、懦夫救星3、福利领取2、使用流程1、灵魂拷问 问&#xff1a;模拟电路很难吗&#xff1f; 答&#xff1a;嗯&#xff0c;真的很难&#xff01;&#xff01;&#xff01; 问&#xff1a;模拟电路容易学吗&#xff1f; 答&#xff1a;很难学&#xff0c;建议放…...

高德地图获得角度

//传入两个经纬度点得到车辆角度 设置车辆Marker角度 getAngle(startPoint, endPoint) {if (!(startPoint && endPoint)) {return 0;}let dRotateAngle Math.atan2(Math.abs(startPoint.lng - endPoint.lng),Math.abs(startPoint.lat - endPoint.lat));console.log(&q…...

【C++】-- C++11基础常用知识点(下)

上篇&#xff1a; 【C】-- C11基础常用知识点&#xff08;上&#xff09;_川入的博客-CSDN博客 目录 新的类功能 默认成员函数 可变参数模板 可变参数 可变参数模板 empalce lambda表达式 C98中的一个例子 lambda表达式 lambda表达式语法 捕获列表 lambda表达底层 …...