二叉树---java---黑马

news2024/9/22 11:54:33

二叉树

遍历

遍历分两种

广度优先遍历

尽可能先访问距离根节点最近的节点,也称之为层序遍历。
在这里插入图片描述

深度优先遍历

对于二叉树,进一步分为三种

  1. pre-order前序遍历,对于每一颗子树,先访问该节点,然后是左子树,最后是右子树;
  2. in-order中序遍历,对于每一颗子树,先访问左子树,然后是该节点,最后是右子树;
  3. post-order后序遍历,对于每一颗子树,先访问左子树,然后是右子树,最后是该节点;
使用递归方式实现
前序遍历
public class TreeNode{
    TreeNode left;
    int value;
    TreeNode right;
    
    public TreeNode() {
        
    }
    
    public TreeNode(TreeNode left, int value, TreeNode) {
        this.left = left;
        this.value = value;
        this.right = right;
    }
    
    @Override
    public String toString() {
        return 	String.valueOf(this.value);
    }
}
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
    }
    
    public void preOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        System.out.println(node.value + "\t");	// 值
        preOrder(node.left);					// 左
        preOrder(node.right);					// 右
    }
    
    public void inOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        preOrder(node.left);					// 左
        System.out.println(node.value + "\t");	// 值
        preOrder(node.right);					// 右
    }
    
    public void postOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        preOrder(node.left);					// 左
        preOrder(node.right);					// 右
        System.out.println(node.value + "\t");	// 值
    }
    
}
非递归实现
前序遍历和中序遍历
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
        Stack<Integer> stack = new Stack<>();
        TreeNode curr = root;
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                System.out.println(curr.value);		// 前序遍历
                stack.push(curr);
                curr = curr.left;
            } else {
                TreeNode pop = stack.pop();
                System.out.println(pop.value);		// 中序遍历
                curr = pop.right;
            }
        }
    }
}
后序遍历
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
        Stack<Integer> stack = new Stack<>();
        TreeNode curr = root;
        TreeNode pop = null;
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                curr = curr.left;
            } else {
                TreeNode peek = stack.peek();
                if (peek.right == null || peek.right == peek) {
                    pop = stack.pop();
                    System.out.println(pop.value);		// 后序遍历
                } else {
                    curr = peek.right;
                }
            }
        }
    }
}
同时实现前序遍历、中序遍历和后序遍历
public class TreeTraversal{
    
    public static void main(String[] args) {
        TreeNode root = new TreeNode(
            new TreeNode(new TreeNode(4, 2, null)), 
            1, 
            new TreeNode(new TreeNode(5, 3, new TreeNode(6))));
        Stack<Integer> stack = new Stack<>();
        TreeNode curr = root;		// 当前节点
        TreeNode pop = null;		// 最近一次弹栈节点
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                // 待处理左子树
                System.out.println(curr.value);			// 前序遍历
                curr = curr.left;
            } else {
                TreeNode peek = stack.peek();
                // 无右子树
                if (peek.right == null) {
                    System.out.println(peek.value);		// 中序遍历
                    pop = stack.pop();
                    System.out.println(pop.value);		// 后序遍历
                } 
                // 右子树处理完成
                else if (peek.right == peek) {
                    pop = stack.pop();
                    System.out.println(pop.value);		// 后序遍历
                } 
                // 待处理右子树
                else {
                    System.out.println(peek.value);		// 中序遍历
                    curr = peek.right;
                }
            }
        }
    }
}

Leetcode

Leetcode101对称二叉树

public class Leetcode101{
    
    public boolean isSymmetric(TreeNode root) {
        return check(root.left, root.right);
    }
    
    public boolean check(TreeNode left, TreeNode right) {
        if (left == null && right == null) {
            return true;
        }
        if (right == null || left == null) {
            return false;
        }
        if (left.value != right.value) {
            return false;
        }
        return check(left.left, right.right) && check(left.right, right.left);
    }
}

Leetcode104最大深度

方法一

使用递归

public class Leetcode104{
    
   	public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        int i = maxDepth(root.left);
        int j = maxDepth(root.right);
        return Math.max(i, j) + 1;
    }
}
方法二

使用后序遍历

public class Leetcode104{
    
   	public int maxDepth(TreeNode root) {
        TreeNode curr = root;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pop = null;		// 最近一次弹栈元素/节点
        int max = 0;				// 栈的最大深度
        while(curr != null || !stack.isEmpty()) {
            if (curr != null) {
                stack.push(curr);
                if (stack.size() > max) {
                    max = stack.size();
                }
                curr = curr.next;
            } else {
                TreeNode peek = stack.peek();
                if (peek.right == null || peek.right == pop) {
                    pop = stack.pop();
                } else {
                    curr = peek.right;
                }
            }
        }
    }
}
方法三

使用层序遍历

public class Leetcode104{
    
   	public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int depth = 0;
        while(!queue.isEmpty()) {
            int size = queue.size();		// 写在循环内,需要多次调用,所以写在循环外
            for(int i = 0; i < size; i++) {
                TreeNode poll = queue.poll();
                if (poll.left != null) {
                    queue.offer(poll.left);
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                }
            }
            depth++;
        }
        return depth;
    }
}

Leetcode111二叉树最小深度

方法一
public class Leetcode111{
    
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int d1 = minDepth(root.left);
        int d2 = minDepth(root.right);
        if (d1 == 0) {	// 当左子树为空
            return d2 + 1;
        } 
        if (d2 == 0) {	// 当右子树为空
            return d1 + 1;
        }
        return Math.min(d1, d2) + 1;
    }
}
方法二

使用层序遍历实现,找到第一个叶子节点,求得最小深度

public class Leetcode111{
    
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        LinkedList<TreeNode> queue = new LinkedList<>();	// LinkedList可以作为双向链表、队列、栈
        queue.offer(root);
        int c1 = 1;
        int depth = 0;
        while (!queue.isEmpty()) {
            int c2 = 0;
            depth++;
            for(int i = 0; i < c1; i++) {
                TreeNode poll = queue.poll();
                if (poll.left == null && poll.right == null) {
                    return depth;
                }
                if (poll.left != null) {
                    queue.offer(poll.left);
                    c2++;
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                    c2++;
                }
            }
            c1 = c2;
        }
        return depth;
    }
}

Leetcode226

二叉树反转

public class Leetcode226{
    public TreeNode invertTree(TreeNode root) {
        if (root == null ||(root.left == null && root.right == null)) {
            return root;
        }
        fn(root);
        return root;
    }
    
    public void fn(TreeNode node) {
        if (node == null) {
            return;
        }
        TreeNode temp = node.left;
        node.left = node.right;
        node.right = temp;
        fn(node.left);
        fn(node.right);
    }
}

后缀表达式构建二叉树

中缀表达式				(2 - 1) * 3
后缀表达式/逆波兰表达式	21-3*
    
    表达树
    *
   / \
  -   3
 / \
2   1 
public class ExpressionTree{
    
    public TreeNode constructExpressionTree (String[] tokens){
        Stack<TreeNode> stack = new Stack<>();
        for(String t : tokens) {
            switch (t) {
                case "+", "-", "*", "/" -> {	// 运算符
                    TreeNode right = stack.pop();
                    TreeNode left = stack.pop();
                    TreeNode parent = new TreeNode(t);
                    parent.left = left;
                    parent.right = right;
                    stack.push(parent);
                }
                default -> {					// 数字
                    stack.push(new TreeNode(t));
                }    
            }
        }
        return stack.peek();
    }
}

Leetcode105

根据前序遍历和中序遍历,得到二叉树

public class Leetcode105{
    public TreeNode buildTree(int[] preOrder, int inOrder) {
        if (preOrder.length == 0) {
            return null;
        }
        // 创建根节点
        int rootValue = preOrder[0];
        TreeNode root = new TreeNode(rootValue);
        for(int i = 0; i < inOrder.length; i++) {
            if (inOrder[i] == rootValue) {
                int[] inLeft = Arrays.copyOfRange(inOrder, 0, i);
                int[] inRight = Arrays.copyOfRange(inOrder, i + 1, inOrder.length);
                
                int[] preLeft = preLeftArrays.copyOfRange(preOrder, 1, i + 1);
                int[] preRight = Arrays.copyOfRange(preOrder, i + 1, preOrder.length);
                
                root.left = buildTree(preLeft, inLeft);
                root.right = buildTree(preRight, inRight);
                break;
            }
        }
        return root;
    }
}

Leetcode106

根据中序遍历和后序遍历得到二叉树

public class Leetcode106{
    public TreeNode buildTree(int[] inOrder, int postOrder) {
        if (postOrder.length == 0) {
            return null;
        }
        // 创建根节点
        int rootValue = postOrder[postOrder.length - 1];
        TreeNode root = new TreeNode(rootValue);
        for(int i = 0; i < inOrder.length; i++) {
            if (inOrder[i] == rootValue) {
                int[] inLeft = Arrays.copyOfRange(inOrder, 0, i);
                int[] inRight = Arrays.copyOfRange(inOrder, i + 1, inOrder.length);
                
                int[] postLeft = preLeftArrays.copyOfRange(preOrder, 0, i);
                int[] postRight = Arrays.copyOfRange(preOrder, i, preOrder.length - 1);
                
                root.left = buildTree(inLef, tpostLeft);
                root.right = buildTree(inRight, postRight);
                break;
            }
        }
        return root;
    }
}
            int[] inRight = Arrays.copyOfRange(inOrder, i + 1, inOrder.length);
            
            int[] postLeft = preLeftArrays.copyOfRange(preOrder, 0, i);
            int[] postRight = Arrays.copyOfRange(preOrder, i, preOrder.length - 1);
            
            root.left = buildTree(inLef, tpostLeft);
            root.right = buildTree(inRight, postRight);
            break;
        }
    }
    return root;
}

}

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

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

相关文章

银河麒麟桌面操作系统如何添加WPS字体

银河麒麟桌面操作系统如何添加WPS字体 1、使用场景2、操作方法步骤一&#xff1a;下载字体文件步骤二&#xff1a;打开终端步骤三&#xff1a;进入字体文件所在目录步骤四&#xff1a;拷贝字体文件到WPS字体目录步骤五&#xff1a;更新字体缓存步骤六&#xff1a;重启WPS Offic…

C++ 把字符串转换成整数 (atoi) - 力扣(LeetCode)

点击链接即可查看&#xff1a;LCR 192. 把字符串转换成整数 (atoi) - 力扣&#xff08;LeetCode&#xff09; 一、题目 请你来实现一个 myAtoi(string s) 函数&#xff0c;使其能将字符串转换成一个 32 位有符号整数&#xff08;类似 C/C 中的 atoi 函数&#xff09;。 函数 my…

基于协同过滤算法的商品推荐系统

系统展示 用户前台界面 管理员后台界面 商家后台界面 系统背景 随着互联网技术的飞速发展&#xff0c;用户每天面临的信息量呈爆炸式增长&#xff0c;如何有效地筛选出用户感兴趣的内容成为一大挑战。在此背景下&#xff0c;基于协同过滤算法的商品推荐系统应运而生。该系统通过…

Th:1.1 建立连接

基础讲解 1.TCP通信流程 基于TCP通信的Socket基本流程: 1.1 Socket 函数返回值&#xff1a;一个文件描述符&#xff1a; 特别的两个队列。 #include <sys/types.h> #include <sys/socket.h> //create an endpoint for communication int socket(int …

【Mysql】Centos 安装 Mysql8.0

官网下载安装包 官网地址&#xff1a;MySQL :: Download MySQL Community Server 查看服务器的名称和版本号 lsb_release -a 查看服务的架构 uname -m 下载对应的版本&#xff0c;这里操作系统选择 Red Hat 就可以了。&#xff08;CentOS 就是将 RHEL 发行的源代码从新编译…

基于redis的HyperLogLog数据结构实现的布隆过滤器在信息流中历史数据的应用

一、基于redis的HyperLogLog数据结构实现的布隆过滤器在信息流中历史数据的应用 做信息流服务端的左发一定会遇到用户历史数据的集合&#xff0c;对于一些有限信息流&#xff08;因DT数据中心的推荐数据变化较慢&#xff0c;推荐量不大&#xff09;&#xff0c;历史数据可以使用…

Abaqus 2024百度云下载:附中文安装包+教程

正如大家所熟知的&#xff0c;Abaqus是一款有限元分析软件&#xff0c;能够高效的配合工程师完成创作。它可以高精度地实现包括金属、橡胶、高分子材料、复合材料、钢筋混凝土、可压缩超弹性泡沫材料以及土壤和岩石等地质材料的工程仿真计算。 “Abaqus”不仅具有出色的仿真计…

TomCat乱码问题

TomCat控制台乱码问题 乱码问题解决&#xff1a; 响应乱码问题 向客户端响应数据&#xff1a; package Servlet;import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servl…

【pyVista】在三维模型中的网格属性

一&#xff0c;什么是属性&#xff1f; 属性是存在于 一个网格。在 PyVista 中&#xff0c;我们同时使用点数据和单元数据&#xff0c;并且 允许轻松访问数据字典以保存属性数组 它们位于网格的所有点或所有单元上。 点数据 点数据是指值数组&#xff08;标量、向量等&#x…

https的连接过程

根证书: 内置在操作系统和浏览器中,可手动添加,下级是中间证书或服务器证书,只有当中间证书或服务器证书关联到已存在的根证书时,中间证书或服务器证书才视为有效 中间证书: 位于根证书和服务器证书之间,他们之间也可以没有中间证书,作用是对根证书增加一个下级,方便管理,由根…

一款批量下载 B 站动态页图片的脚本

在逛 B 站的时候&#xff0c;总能看到不少 UP 会发很多图片&#xff0c;此时一个一个保存非常麻烦&#xff0c;而且文件名都是随机的字符串&#xff0c;还得手工重命名。 为此&#xff0c;特地搜索了下有没相关的浏览器插件或油猴脚本&#xff0c;还真给我找到一个。 脚本地址…

Kafka 下载安装及使用总结

1. 下载安装 官网下载地址&#xff1a;Apache Kafka 下载对应的文件 上传到服务器上&#xff0c;解压 tar -xzf kafka_2.13-3.7.0.tgz目录结果如下 ├── bin │ └── windows ├── config │ └── kraft ├── libs ├── licenses └── site-docs官方文档…

专注并不意味只做一件事

原创内容第658篇&#xff0c;专注量化投资、个人成长与财富自由。 财务自由本身就是一个很有争议的领域。 有谁能靠别人实现财富自由呢&#xff1f; 这个逻辑起点本身就有问题。 如果预期正确&#xff0c;那这些自媒体还是有用处的。 好比我现在对于阅读和书籍的预期&…

深入解析 Apache Doris架构、应用场景与最佳实践

一、Doris 简介 Apache Doris 是一款现代化的 MPP&#xff08;Massively Parallel Processing&#xff09;数据库&#xff0c;专注于解决大规模数据分析和实时查询的需求。它最初源自百度的 Palo 项目&#xff0c;随后贡献给了 Apache 基金会&#xff0c;并在开源社区的共同努…

『功能项目』QFrameWork框架重构OnGUI【63】

我们打开上一篇62QFrameWork背包框架的项目&#xff0c; 上文将功能实现在一个脚本中 本章要做的事情让脚本实现背包框架思想 首先按照图示创建脚本&#xff1a; 创建脚本&#xff1a;Item.cs namespace QFramework {public class Item{//道具public string Key;public string …

【CSS in Depth 2 精译_033】5.4 Grid 网格布局的显式网格与隐式网格(中)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

C++速通LeetCode中等第18题-删除链表的倒数第N个结点(最简单含注释)

绝妙&#xff01;快慢指针法,快指针先走n步&#xff08;复杂度O(n),O(1))&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(n…

GS-SLAM论文阅读笔记--TAMBRIDGE

前言 本文提出了一个自己的分类方法&#xff0c;传统的视觉SLAM通常使用以帧为中心的跟踪方法&#xff0c;但是3DGS作为一种高效的地图表达方法好像更侧重于地图的创建。这两种方法都有各自的优缺点&#xff0c;但是如果能取长补短&#xff0c;互相结合&#xff0c;那么就会是…

STM32精确控制步进电机

目的&#xff1a;学习使用STM32电机驱动器步进电机&#xff0c;进行电机运动精确控制。 测试环境&#xff1a; MCU主控芯片STM32F103RCT6 &#xff1b;A4988步进电机驱动器模块&#xff1b;微型2相4线步进电机10mm丝杆滑台&#xff0c;金属丝杆安装有滑块。 10mm二相四线微型…

我的AI工具箱Tauri版-FasterWhisper音频转文本

本教程基于自研的AI工具箱Tauri版进行FasterWhisper音频转文本服务。 FasterWhisper音频转文本服务 是自研AI工具箱Tauri版中的一款模块&#xff0c;专门用于将音频或视频中的语音内容自动转化为文本或字幕。通过简单的配置&#xff0c;该工具能够批量处理大量音频或视频文件&…