二叉树相关题目

一、概念

二、题目

2.1 把数组转换成二叉树

2.2.1 使用队列方式

public static Node getTreeFromArr2(int[] arr) {
        if (arr == null || arr.length == 0) {
            return null;
        }

        LinkedList<Node> quque = new LinkedList<>();
        Node root = new Node(arr[0]);

        quque.add(root);
        int index = 1;
        while(!quque.isEmpty()){
            // pop 0的时候,刚好操作1、2
            // pop 1的时候,刚好操作3、4
            // pop 2的时候,刚好操作5、6
            Node temp = quque.pop();
            if(index < arr.length){
                temp.left = new Node(arr[index]);
                quque.add(temp.left);
                index++;
            }

            if(index < arr.length){
                temp.right = new Node(arr[index]);
                quque.add(temp.right);
                index++;
            }
        }
        return root;
    }

2.2.3 使用堆的方式

private static Node getTreeFromArr(int[] arr) {
        Map<Integer, Node> map = new HashMap();
        for (int i = arr.length - 1; i >= 0; i--) {
            Node temp = new Node(arr[i]);
            temp.value = arr[i];
            map.put(i, temp);
            int leftChildIndex = 2 * i + 1;
            int rightChildIndex = 2 * i + 2;
            if (leftChildIndex < arr.length) {
                temp.left = map.get(leftChildIndex);
            }
            if (rightChildIndex < arr.length) {
                temp.right = map.get(rightChildIndex);
            }
        }
        return map.get(0);
    }

2.2 二叉树进行前序、中序、后序遍历

2.2.1 递归的方式

@ToString
    public static class Node {
        public Node left;
        public Node right;
        public int value;

        public Node(int value) {
            this.value = value;

        }
    }

    public static void main(String[] args) {
        int[] arr = {0, 1, 2, 3, 4, 5, 6};
//        Node head = getTreeFromArr(arr);
        Node head2 = getTreeFromArr2(arr);
//        System.out.println(JSON.toJSONString(head));
        System.out.println(JSON.toJSONString(head2));

        /*
            前序遍历:[0, 1, 3, 4, 2, 5, 6]
            中序遍历:[3, 1, 4, 0, 5, 2, 6]
            后序遍历:[3, 4, 1, 5, 6, 2, 0]
         */
        preorderPrint(head2);
        System.out.println();
        inorderPrint(head2);
        System.out.println();
        postorderPrint(head2);
    }

    /**
     * 前序遍历(中左右)
     */
    public static void preorderPrint(Node temp){
        if(null == temp){
            return;
        }
        System.out.print(temp.value + ",");
        preorderPrint(temp.left);
        preorderPrint(temp.right);
    }

    /**
     * 中序遍历(左中右)
     */
    public static void inorderPrint(Node temp){
        if(null == temp){
            return;
        }
        inorderPrint(temp.left);
        System.out.print(temp.value + ",");
        inorderPrint(temp.right);
    }
    /**
     * 右序遍历(左中右)
     */
    public static void postorderPrint(Node temp){
        if(null == temp){
            return;
        }
        postorderPrint(temp.left);
        postorderPrint(temp.right);
        System.out.print(temp.value + ",");
    }


    public static Node getTreeFromArr2(int[] arr) {
        if (arr == null || arr.length == 0) {
            return null;
        }

        LinkedList<Node> quque = new LinkedList<>();
        Node root = new Node(arr[0]);

        quque.add(root);
        int index = 1;
        while(!quque.isEmpty()){
            // pop 0的时候,刚好操作1、2
            // pop 1的时候,刚好操作3、4
            // pop 2的时候,刚好操作5、6
            Node temp = quque.pop();
            if(index < arr.length){
                temp.left = new Node(arr[index]);
                quque.add(temp.left);
                index++;
            }

            if(index < arr.length){
                temp.right = new Node(arr[index]);
                quque.add(temp.right);
                index++;
            }
        }
        return root;
    }

2.2.2 栈的方式

1、前序遍历(宽度遍历)

/**
     * Stack方法
     * 前序遍历(中左右)
     */
    public static void preorderPrintByStack(Node root) {
        Stack<Node> stack = new Stack<>();
        stack.push(root);

        // 可以不用queue,可以直接打印,省空间 N
        // 我加一个 queue的目的是为了后序的翻转好理解
        Queue<Node> queue = new LinkedList<>();

        while (!stack.isEmpty()) {
            Node temp = stack.pop();
//            System.out.print(temp.value + ",");
            // 此处可以不打印,直接入一个新的 queue
            queue.offer(temp);
            if (temp.right != null) {
                stack.push(temp.right);
            }
            if (temp.left != null) {
                stack.push(temp.left);
            }
        }
        System.out.print("preorderPrintByStack -> ");
        while (!queue.isEmpty()) {
            System.out.print(queue.poll().value + ",");
        }
        System.out.println();
    }
/**
     * 宽度遍历,其实就是中左右,也就是前序遍历
     * 用一个 queue 辅助也是可以搞定的
     * @param head
     */
    public static void widthPrint(Node head){
        if(null == head){
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.offer(head);

        while(!queue.isEmpty()){
            Node temp = queue.poll();
            System.out.print(temp.value + ",");
            if(temp.left != null){
                queue.offer(temp.left);
            }
            if(temp.right != null){
                queue.offer(temp.right);
            }
        }
    }
2、中序遍历


    /**
     * Stack方法
     * 中序遍历(左中右)
     */
    public static void inOrderPrintByStack(Node root) {
        if(null == root){
            return;
        }
        Node current = root;
        Stack<Node> stack = new Stack<>();

        // 可以不用queue,可以直接打印,省空间 N
        // 我加一个 queue的目的是为了后序的翻转好理解
        Queue<Node> queue = new LinkedList<>();

        while (current != null || !stack.isEmpty()) {
            // 如果current不是null,那么就一直往左找下去
            while(current != null){
                stack.push(current);
                current = current.left;
            }
            current = stack.pop();
//            System.out.print(current.value + ",");
            queue.offer(current);
            // 左边已经干完了,那么就一直往右找
            current = current.right;
        }

        System.out.print("inOrderPrintByStack -> ");
        while (!queue.isEmpty()) {
            System.out.print(queue.poll().value + ",");
        }
    }
3、右序遍历

/**
     * 右序遍历(左右中)
     * 翻过来就是 中右左, 因为前序是中左右,前序是先压right再压left,那么反过来,先压left再压right的话,就会是中右左了
     */
    public static void postorderPrintByStack(Node temp) {
        if (null == temp) {
            return;
        }
        Stack<Node> stackA = new Stack<>();
        stackA.push(temp);

        // 注意和之前的区别,上面的中序和前序都是 queue ,FIFO,那么 Stack 的FILO,就能实现这个翻转
        Stack<Node> stackB = new Stack<>();

        while(!stackA.isEmpty()){
            temp = stackA.pop();
            stackB.push(temp);
            if(temp.left != null){
                stackA.push(temp.left);
            }
            if(temp.right != null){
                stackA.push(temp.right);
            }
        }

        System.out.print("postorderPrintByStack -> ");
        while (!stackB.isEmpty()) {
            System.out.print(stackB.pop().value + ",");
        }
    }
0、测试代码汇总
@ToString
    public static class Node {
        public Node left;
        public Node right;
        public int value;

        public Node(int value) {
            this.value = value;

        }
    }

    public static void main(String[] args) {
        int[] arr = {0, 1, 2, 3, 4, 5, 6};
//        Node head = getTreeFromArr(arr);
        Node head2 = getTreeFromArr2(arr);
//        System.out.println(JSON.toJSONString(head));
        System.out.println(JSON.toJSONString(head2));

        /*
            前序遍历:[0, 1, 3, 4, 2, 5, 6]
            中序遍历:[3, 1, 4, 0, 5, 2, 6]
            后序遍历:[3, 4, 1, 5, 6, 2, 0]
         */

        System.out.println("preorderPrint ->");
        preorderPrint(head2);
        System.out.println();

        System.out.println("inorderPrint ->");
        inorderPrint(head2);
        System.out.println();

        System.out.println("postorderPrint ->");
        postorderPrint(head2);
        System.out.println();
        System.out.println("——————————");


        preorderPrintByStack(head2);
        inOrderPrintByStack(head2);
        postorderPrintByStack(head2);
    }

    /**
     * 前序遍历(中左右)
     */
    public static void preorderPrint(Node temp) {
        if (null == temp) {
            return;
        }
        System.out.print(temp.value + ",");
        preorderPrint(temp.left);
        preorderPrint(temp.right);
    }

    /**
     * 中序遍历(左中右)
     */
    public static void inorderPrint(Node temp) {
        if (null == temp) {
            return;
        }
        inorderPrint(temp.left);
        System.out.print(temp.value + ",");
        inorderPrint(temp.right);
    }

    /**
     * 右序遍历(左中右)
     */
    public static void postorderPrint(Node temp) {
        if (null == temp) {
            return;
        }
        postorderPrint(temp.left);
        postorderPrint(temp.right);
        System.out.print(temp.value + ",");
    }

    /**
     * Stack方法
     * 前序遍历(中左右)
     */
    public static void preorderPrintByStack(Node root) {
        Stack<Node> stack = new Stack<>();
        stack.push(root);

        // 可以不用queue,可以直接打印,省空间 N
        // 我加一个 queue的目的是为了后序的翻转好理解
        Queue<Node> queue = new LinkedList<>();

        while (!stack.isEmpty()) {
            Node temp = stack.pop();
//            System.out.print(temp.value + ",");
            // 此处可以不打印,直接入一个新的 queue
            queue.offer(temp);
            if (temp.right != null) {
                stack.push(temp.right);
            }
            if (temp.left != null) {
                stack.push(temp.left);
            }
        }
        System.out.print("preorderPrintByStack -> ");
        while (!queue.isEmpty()) {
            System.out.print(queue.poll().value + ",");
        }
        System.out.println();
    }

    /**
     * Stack方法
     * 中序遍历(左中右)
     */
    public static void inOrderPrintByStack(Node root) {
        if(null == root){
            return;
        }
        Node current = root;
        Stack<Node> stack = new Stack<>();

        // 可以不用queue,可以直接打印,省空间 N
        // 我加一个 queue的目的是为了后序的翻转好理解
        Queue<Node> queue = new LinkedList<>();

        while (current != null || !stack.isEmpty()) {
            // 如果current不是null,那么就一直往左找下去
            while(current != null){
                stack.push(current);
                current = current.left;
            }
            current = stack.pop();
//            System.out.print(current.value + ",");
            queue.offer(current);
            // 左边已经干完了,那么就一直往右找
            current = current.right;
        }

        System.out.print("inOrderPrintByStack -> ");
        while (!queue.isEmpty()) {
            System.out.print(queue.poll().value + ",");
        }
    }


    /**
     * 右序遍历(左右中)
     * 翻过来就是 中右左, 因为前序是中左右,前序是先压right再压left,那么反过来,先压left再压right的话,就会是中右左了
     */
    public static void postorderPrintByStack(Node temp) {
        if (null == temp) {
            return;
        }
        Stack<Node> stackA = new Stack<>();
        stackA.push(temp);

        // 注意和之前的区别,上面的中序和前序都是 queue ,FIFO,那么 Stack 的FILO,就能实现这个翻转
        Stack<Node> stackB = new Stack<>();

        while(!stackA.isEmpty()){
            temp = stackA.pop();
            stackB.push(temp);
            if(temp.left != null){
                stackA.push(temp.left);
            }
            if(temp.right != null){
                stackA.push(temp.right);
            }
        }

        System.out.print("postorderPrintByStack -> ");
        while (!stackB.isEmpty()) {
            System.out.print(stackB.pop().value + ",");
        }
    }




    public static Node getTreeFromArr2(int[] arr) {
        if (arr == null || arr.length == 0) {
            return null;
        }

        LinkedList<Node> quque = new LinkedList<>();
        Node root = new Node(arr[0]);

        quque.add(root);
        int index = 1;
        while (!quque.isEmpty()) {
            // pop 0的时候,刚好操作1、2
            // pop 1的时候,刚好操作3、4
            // pop 2的时候,刚好操作5、6
            Node temp = quque.pop();
            if (index < arr.length) {
                temp.left = new Node(arr[index]);
                quque.add(temp.left);
                index++;
            }

            if (index < arr.length) {
                temp.right = new Node(arr[index]);
                quque.add(temp.right);
                index++;
            }
        }
        return root;
    }

2.3 求一颗二叉树的宽度

private static void getTreeWidth(Node root) {
        System.out.println();
        System.out.println("---getTreeWidth---");
        Node temp = root;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(temp);

        int maxLevelSize = 0;
        while (!queue.isEmpty()) {
            int levelSize = queue.size();
            maxLevelSize = Math.max(maxLevelSize,levelSize);
            // 思路就是:for完结束之后,才会进入下一层
            for (int i = 0; i < levelSize; i++) {
                temp = queue.poll();
                System.out.print(temp.value + ",");
                if (temp.left != null) {
                    queue.offer(temp.left);

                }
                if (temp.right != null) {
                    queue.offer(temp.right);
                }
            }
        }
        System.out.println("maxLevelSize -> " + maxLevelSize);
    }

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

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

相关文章

单片机FLASH下载算法的制作

环境 硬件使用正点原子STM32F407探索者V2开发板 编程环境使用MDK 下载工具使用JLINK FLASH芯片使用W25Q128 什么是下载算法 单片机FLASH的下载算法是一个FLM文件&#xff0c;FLM通过编译链接得到&#xff0c;其内部包含一系列对FLASH的操作&#xff0c;包括初始化、擦除、写…

delphi电子处方流转(药店)

【delphi电子处方流转(药店)】支持 处方下载、处方核验、处方审核、药品销售出库明细上传、药品销售出库明细撤销等功能。

【Java 语言】读取 properties 配置文件 ( Java 语言中的 properties 配置文件 | 使用 properties 配置文件 )

文章目录 一、Java 语言中的 properties 配置文件二、使用 properties 配置文件三、完整代码示例1、Java 代码2、properties 配置文件3、执行结果 一、Java 语言中的 properties 配置文件 Java 语言中 , properties 配置文件 是一种用于存储应用程序配置信息的文本文件 ; prop…

腾讯云服务器多少钱一年?腾讯云服务器88元一年,附优惠购买入口

腾讯云服务器可以以低至88元一年的价格购买&#xff01;这个价格可以说是非常实惠。现在&#xff0c;让我们一起来了解腾讯云服务器的价格以及如何购买优惠的服务器。 如何购买88元一年的腾讯云服务器&#xff1f; 购买腾讯云服务器非常简单&#xff0c;只需按照以下步骤&…

Odoo 15开发手册第四章 模块继承

Odoo 的一项强大之处是无需直接修改所扩展模块的代码即可添加功能。这都归功于与自身代码组件相独立的功能继承。对模块的扩展可通过继承机制实现&#xff0c;以已有对象的修改层的形式。这些修改可以发生在每个层面&#xff0c;包括模型、视图和业务逻辑层面。我们不是直接修改…

idea查看UML类图

idea查看UML类图 一、如何查看UML类图 1.1 选择需要查看的类或者包&#xff0c;鼠标右键&#xff0c;选择Diagrams->Show Diagram 1.2 对于UML类图中的包&#xff0c;选中后点击鼠标右键-> Expand Nodes(展开节点) 展开前 展开后 1.3 展开后分布比较凌乱&#xff…

Axure基础详解二十二:随机点名效果

效果演示 组件 建立一个【中继器】&#xff0c;内部插入一个“文本框”。【中继器】每页项目数为1&#xff0c;开始页为1。 设置交互 页面载入时交互 给【中继器】新曾行&#xff0c;“name”数据列添加10行数据&#xff0c;填入相应的名字&#xff1b;“shunxu”数据列全部…

GLSL: Shader cannot be patched for instancing.

最近在 unity 里碰到了这么一个错误&#xff0c;只有这么点信息&#xff0c;让人看着挺懵逼的&#xff0c;后来发现&#xff0c;是因为 unity 的 terrain 组件在设置里勾了 Draw Instanced 选项导致的&#xff0c;感觉应该是 unity 的 bug。 因为错出在 2021&#xff0c;2022就…

ZYNQ_project:test_fifo_255X8

首先&#xff0c;这个vivado的fifo和quartus有很大不同。 用BRAM来实现异步fifo。 vivado的fifo有复位&#xff0c;在时钟信号稳定后&#xff0c;复位至少三个时钟周期&#xff08;读写端口的慢时钟&#xff09;&#xff0c;复位完成后30个时钟周期后再进行写操作&#xff08…

网络安全-黑客技术(自学笔记)

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c;但是连方向都没搞清楚就开始学习…

python基于DETR(DEtection TRansformer)开发构建人员手持物品检测识别分析系统

PyTorch训练代码和DETR&#xff08;DEDetection-TRansformer&#xff09;的预训练模型。我们用Transformer替换了完全复杂的手工制作的对象检测管道&#xff0c;并将Faster R-CNN与ResNet-50匹配&#xff0c;使用一半的计算能力&#xff08;FLOP&#xff09;和相同数量的参数在…

vue3路由

vue3路由总结 vue3路由安装和引入&#xff1a;路由配置、创建 Router 实例&#xff1a;导航守卫 使用路由返回上一个页面没有跳转指定页 vue3路由 Vue3 路由是 Vue.js 3.x 版本中用于管理页面跳转和导航的模块。它基于 Vue Router 4.x&#xff0c;相较于 Vue2 的路由机制&…

来讲解一手事务隔离级别

简介 在数据库管理系统中&#xff0c;事务是一组被视为单一工作单元的操作&#xff0c;这些操作要么全部执行成功&#xff0c;要么全部回滚。为了确保在多用户并发访问数据库时数据的一致性和可靠性&#xff0c;引入了事务隔离级别的概念。事务隔离级别定义了一个事务对于其他…

餐厅订座预约小程序的效果如何

市场中无论哪种城市&#xff0c;餐厅非常多&#xff0c;一条不长的商业街&#xff0c;汇聚着数家餐饮品牌&#xff0c;且相互间竞争激烈&#xff0c;并且各个商家都希望用成本低高效率的方法引流及转化。 随着互联网深入各个行业&#xff0c;传统餐饮行业经营痛点不少。 传统餐…

(Matalb回归预测)WOA-BP鲸鱼算法优化BP神经网络的多维回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matalb平台编译&#xff0c;将WOA(鲸鱼算法)与BP神…

代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结

代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结 文章链接&#xff1a;两个字符串的删除操作、编辑距离、编辑距离总结 视频链接&#xff1a;两个字符串的删除操作、编辑距离 1. LeetCode 583. 两个字符串的删除操作 1.1 思…

YOLOv8环境搭建

YOLOv8环境搭建 torch环境安装requestment.txt文件中的包安装ultralytics调用 torch环境 使用的是python3.9版本 pip install torch-2.1.0cu118-cp39-cp39-linux_x86_64.whl torchvision0.16.0 torchaudio2.1.0 --index-url https://download.pytorch.org/whl/cu118安装reques…

GUI编程--PyQt5--QTreeWidget

文章目录 树型控件展示数据修改节点数据获取所有节点的数据 Qt模组参考 QWidgets QTreeWidget 树型控件展示数据 展示数据的同时&#xff0c;每个节点标注数据类型。 class MyWindow(QWidget):def __init__(self, title):super(MyWindow, self).__init__()self.setWindowTitl…

【SpringBoot篇】分页查询 | 扩展SpringMvc的消息转换器

文章目录 &#x1f6f8;什么是分页查询&#x1f339;代码实现⭐问题&#x1f384;解决方法 做了几个项目&#xff0c;发现在这几个项目里面&#xff0c;都实现了分页查询效果&#xff0c;所以就总结一下&#xff0c;方便学习 我们基于黑马程序员的苍穹外卖来讲解分页查询的要点…

el-table中el-popover失效问题

场景&#xff1a;先有一个数据表格&#xff0c;右侧操作栏为固定列&#xff0c;另外有一个字段使用了el-popover来点击弹出框来修改值&#xff0c;发现不好用&#xff0c;点击后无法显示弹出框&#xff0c;但当没有操作栏权限时却意外的生效了。 这种问题真是不常见&#xff0…