瑞_数据结构与算法_二叉树

文章目录

    • 1 什么是二叉树
    • 2 二叉树的存储
      • 2.1 使用树节点类TreeNode存储(代码)
      • 2.2 使用数组存储
    • 3 二叉树的遍历
      • 3.1 广度优先遍历
      • 3.2 深度优先遍历
        • 3.2.1 深度优先——前序遍历
        • 3.2.2 深度优先——中序遍历
        • 3.2.3 深度优先——后序遍历
      • 3.3 代码实现
        • 3.3.1 递归实现——深度优先遍历
        • 3.3.2 非递归实现——深度优先遍历
          • 3.3.2.1 前序遍历
          • 3.3.2.2 中序遍历
          • 3.3.2.3 后序遍历
          • 3.3.2.4 非递归实现深度优先——统一写法★★★
    • 力扣题144 二叉树的前序遍历
    • 力扣题94 二叉树的中序遍历
    • 力扣题145. 二叉树的后序遍历

🙊前言:本文章为瑞_系列专栏之《数据结构与算法》的二叉树篇。由于博主是从B站黑马程序员的《数据结构与算法》学习到的相关知识,所以本系列专栏主要针对该课程进行笔记总结和拓展,文中的部分原理及图解也是来源于黑马提供的资料。本文仅供大家交流、学习及研究使用,禁止用于商业用途,违者必究!

在这里插入图片描述

1 什么是二叉树

  二叉树是一种树状结构:每个节点最多有两个孩子,左孩子和右孩子。

  重要的二叉树结构:

  • 完全二叉树(complete binary tree)是一种二叉树结构,除最后一层以外,每一层都必须填满,填充时要遵从先左后右。
  • 平衡二叉树(balance binary tree)是一种二叉树结构,其中每个节点的左右子树高度相差不超过 1 。



2 二叉树的存储

  二叉树的存储方式一般分为:使用树节点类TreeNode存储、使用数组存储。

2.1 使用树节点类TreeNode存储(代码)

  定义树节点与左、右孩子引用(TreeNode),参考代码如下:

public class TreeNode {
    /**
     * 节点值
     */
    public int val;
    /**
     * 左孩子
     */
    public TreeNode left;
    /**
     * 右孩子
     */
    public TreeNode right;

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

    public TreeNode(TreeNode left, int val, TreeNode right) {
        this.left = left;
        this.val = val;
        this.right = right;
    }

    @Override
    public String toString() {
        return String.valueOf(this.val);
    }
}

2.2 使用数组存储

  类似于使用数组实现堆,数组索引为 0 处即是根节点,索引为 1 处即是根节点的左孩子,索引为 2 处即是根节点的右孩子,没有元素则使用null表示。

  若以 0 作为树的根,索引可以通过如下方式计算:

  • 父 = floor((子 - 1) / 2)
  • 左孩子 = 父 * 2 + 1
  • 右孩子 = 父 * 2 + 2

瑞:实际过程中按照业务需求自己选定,两种存储的表示方式都可行,没有对错,只有适合和更适合




3 二叉树的遍历

  遍历主要分为以下两种:

  1. 广度优先遍历(Breadth-first order):尽可能先访问距离根最近的节点,也称为层序遍历
  2. 深度优先遍历(Depth-first order):对于二叉树,可以进一步分成三种(要深入到叶子节点)
    1. pre-order 前序遍历,对于每一棵子树,先访问该节点,然后是左子树,最后是右子树
    2. in-order 中序遍历,对于每一棵子树,先访问左子树,然后是该节点,最后是右子树
    3. post-order 后序遍历,对于每一棵子树,先访问左子树,然后是右子树,最后是该节点

3.1 广度优先遍历

  广度优先遍历(Breadth-first order):尽可能先访问距离根最近的节点,也称为层序遍历,即“Z”字型遍历,如下图:

在这里插入图片描述
  用队列来层序遍历是针对 TreeNode 这种方式表示的二叉树,如下表所示:

本轮开始时队列本轮访问节点
[1]1
[2, 3]2
[3, 4]3
[4, 5, 6]4
[5, 6]5
[6, 7, 8]6
[7, 8]7
[8]8
[]

  如上表所示,步骤为:

  1. 初始化,将根节点加入队列
  2. 循环处理队列中每个节点,直至队列为空
  3. 每次循环内处理节点后,将它的孩子节点(即下一层的节点)加入队列

  对于数组表现的二叉树,则直接遍历数组即可,自然为层序遍历的顺序

3.2 深度优先遍历


  深度优先遍历(Depth-first order):对于二叉树,可以进一步分成三种(要深入到叶子节点)

  1. pre-order 前序遍历,对于每一棵子树,先访问该节点,然后是左子树,最后是右子树
  2. in-order 中序遍历,对于每一棵子树,先访问左子树,然后是该节点,最后是右子树
  3. post-order 后序遍历,对于每一棵子树,先访问左子树,然后是右子树,最后是该节点

在这里插入图片描述

3.2.1 深度优先——前序遍历

  前序遍历规则:

  • 先访问该节点
  • 然后是左子树
  • 最后是右子树

  按照前序遍历规则,执行顺序为:先访问根节点1(打印1),然后访问根节点1的左子树2(打印2),然后访问2的左子树4(打印4),由于4左右子树为null,所以4访问结束。退回到2,2的左子树已经遍历完了,右子树为null,即2遍历结束。退回到1,1的左子树已经遍历结束,开始遍历1的右子树3(打印3),访问3的左子树5(打印5),5的左右子树为null,退回到3,访问3的右子树6(打印6),前序遍历结束。

前序遍历的结果为:1,2,4,3,5,6
瑞:根左右

3.2.2 深度优先——中序遍历

  中序遍历规则:

  • 先访问左子树
  • 然后是该节点
  • 最后是右子树

  按照中序遍历规则,左子树没遍历完之前是不能打印该节点的值,所以执行顺序为:先访问根节点1(不打印),然后访问根节点1的左子树2(不打印),然后访问2的左子树4(不打印),由于4左子树为null,所以此时打印4(打印4),4的右子树为null,4遍历结束。退回到2,2的左子树已经遍历完了,所以此时打印2(打印2),2的右子树为null,即2遍历结束。退回到1,1的左子树已经遍历结束,此时打印1(打印1),开始遍历1的右子树3(不打印),访问3的左子树5(不打印),5的左子树为null,所以此时打印5(打印5),5的右子树为null,5遍历结束。退回到3,3的左子树已经遍历完了,所以此时打印3(打印3),开始访问3的右子树6(不打印),6的左子树为null,所以此时打印6(打印6),6的右子树为null,中序遍历结束。

中序遍历的结果为:4,2,1,5,3,6
瑞:左根右

3.2.3 深度优先——后序遍历

  后序遍历规则:

  • 先访问左子树
  • 然后是右子树
  • 最后是该节点

  按照后序遍历规则,左右子树没遍历完之前是不能打印该节点的值,所以执行顺序为:先访问根节点1(不打印),然后访问根节点1的左子树2(不打印),然后访问2的左子树4(不打印),由于4左子树为null、右子树为null,所以此时打印4(打印4),4遍历结束。退回到2,2的左子树已经遍历完了,2的右子树为null,所以此时打印2(打印2),即2遍历结束。退回到1,1的左子树已经遍历结束,开始遍历1的右子树3(不打印),开始遍历1的右子树3(不打印),访问3的左子树5(不打印),5的左子树为null、5的右子树为null,所以此时打印5(打印5),5遍历结束。退回到3,3的左子树已经遍历完了,开始访问3的右子树6(不打印),6的左子树为null、6的右子树为null,所以此时打印6(打印6),6遍历结束。退回到3,3的左右子树遍历结束,所以此时打印3(打印3),退回到1,1的左右子树遍历结束,所以此时打印1(打印1) ,后序遍历结束。

后序遍历的结果为:4,2,5,6,3,1
瑞:左右根

瑞:不用特别死记硬背,因为左子树的遍历一定在右子树之前,所以前中后指的就是打印左右节点前该节点的打印顺序。比如前序遍历就是在左右子树遍历前(根左右),中序遍历就是左子树打印完之后打印该节点再打印右子树(左根右),后续遍历就是左右子树打印完再打印该节点(左右根),就是根的位置在左右子树的位置就是前中后序的区别

3.3 代码实现

  以下实现均需要使用TreeNode类,在文章 2.1 使用树节点类TreeNode存储(代码)

  构建本例中的树型结构的代码如下:

        /*
                1
               / \
              2   3
             /   / \
            4   5   6
         */
        TreeNode root = new TreeNode(
                new TreeNode(new TreeNode(4), 2, null),
                1,
                new TreeNode(new TreeNode(5), 3, new TreeNode(6))
        );
3.3.1 递归实现——深度优先遍历

  使用递归实现比较简单,代码如下:

public class TreeTraversal {
    public static void main(String[] args) {
        /*
                1
               / \
              2   3
             /   / \
            4   5   6
         */
        TreeNode root = new TreeNode(
                new TreeNode(new TreeNode(4), 2, null),
                1,
                new TreeNode(new TreeNode(5), 3, new TreeNode(6))
        );
        System.out.print("前序遍历:\t");
        preOrder(root);
        System.out.println();

        System.out.print("中序遍历:\t");
        inOrder(root);
        System.out.println();

        System.out.print("后序遍历:\t");
        postOrder(root);
        System.out.println();
    }

    /**
     * 前序遍历
     *
     * @param node 节点
     */
    static void preOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        System.out.print(node.val + "\t"); // 值
        preOrder(node.left); // 左
        preOrder(node.right); // 右
    }

    /**
     * 中序遍历
     *
     * @param node 节点
     */
    static void inOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        inOrder(node.left); // 左
        System.out.print(node.val + "\t"); // 值
        inOrder(node.right); // 右
    }

    /**
     * 后序遍历
     *
     * @param node 节点
     */
    static void postOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        postOrder(node.left); // 左
        postOrder(node.right); // 右
        System.out.print(node.val + "\t"); // 值
    }
}

以上代码运行结果:
前序遍历: 1 2 4 3 5 6
中序遍历: 4 2 1 5 3 6
后序遍历: 4 2 5 6 3 1

  复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。每一个节点恰好被遍历一次。
  • 空间复杂度:O(n),为递归过程中栈的开销,平均情况下为 O(log⁡ n),最坏情况下树呈现链状,为 O(n)。
3.3.2 非递归实现——深度优先遍历

  由于树型结构中没有保存父节点元素,所以需要使用栈(后进先出特性)来存储来回的路,本质上是在模拟递归,因为在递归的过程中使用了系统栈。可以使用自定义实现的栈类或者使用JDK1.8中自带的LinkedList<E>类,该类实现了Deque接口,即含有栈的相关方法。注意不建议使用Stack类,官方建议使用Deque接口及其实现类来实现的栈功能,具体原因本文不进行阐述。

3.3.2.1 前序遍历
LinkedListStack<TreeNode> stack = new LinkedListStack<>();
TreeNode curr = root;

while (!stack.isEmpty() || curr != null) {
    if (curr != null) {
        stack.push(curr);
        System.out.println(curr);
        curr = curr.left;
    } else {
        TreeNode pop = stack.pop();
        curr = pop.right;
    }

}
3.3.2.2 中序遍历
LinkedListStack<TreeNode> stack = new LinkedListStack<>();
TreeNode curr = root;

while (!stack.isEmpty() || curr != null) {
    if (curr != null) {
        stack.push(curr);
        curr = curr.left;
    } else {
        TreeNode pop = stack.pop();
        System.out.println(pop);
        curr = pop.right;
    }
}
3.3.2.3 后序遍历
LinkedListStack<TreeNode> stack = new LinkedListStack<>();
TreeNode curr = root;
TreeNode pop = null;

while (!stack.isEmpty() || curr != null) {
    if (curr != null) {
        stack.push(curr);
        curr = curr.left;
    } else {
        TreeNode peek = stack.peek();
        if (peek.right == null || peek.right == pop) {
            pop = stack.pop();
            System.out.println(pop);
        } else {
            curr = peek.right;
        }
    }
}

  对于后序遍历,向回走时,需要处理完右子树才能 pop 出栈。如何知道右子树处理完成呢?

  • 如果栈顶元素的 right == null 表示没啥可处理的,可以出栈
  • 如果栈顶元素的 right ≠null,
    • 那么使用 lastPop 记录最近出栈的节点,即表示从这个节点向回走
    • 如果栈顶元素的 right == lastPop 此时应当出栈

  对于前、中两种遍历,实际以上代码从右子树向回走时,并未走完全程(stack 提前出栈了)后序遍历以上代码是走完全程了

3.3.2.4 非递归实现深度优先——统一写法★★★

  下面是一种统一的写法,依据后序遍历修改,可根据前中后需求自定义修改

import java.util.LinkedList;

/**
 * 非递归实现 深度优先遍历 三种遍历通用写法
 *
 * @author LiaoYuXing-Ray
 * @version 1.0
 * @createDate 2024/1/22 15:09
 **/
public class RayTest {
    public static void preorderTraversal(TreeNode root) {
        LinkedList<TreeNode> stack = new LinkedList<>(); // 栈
        TreeNode curr = root; // 代表当前节点
        TreeNode pop = null; // 最近一次弹栈的元素
        while (curr != null || !stack.isEmpty()) {
            if (curr != null) {
                colorPrintln("前: " + curr.val, 31);
                stack.push(curr); // 压入栈,为了记住回来的路
                curr = curr.left;
            } else {
                TreeNode peek = stack.peek();
                // 右子树可以不处理, 对中序来说, 要在右子树处理之前打印
                if (peek.right == null) {
                    colorPrintln("中: " + peek.val, 35);
                    pop = stack.pop();
                    colorPrintln("后: " + pop.val, 34);
                }
                // 右子树处理完成, 对中序来说, 无需打印
                else if (peek.right == pop) {
                    pop = stack.pop();
                    colorPrintln("后: " + pop.val, 34);
                }
                // 右子树待处理, 对中序来说, 要在右子树处理之前打印
                else {
                    colorPrintln("中: " + peek.val, 35);
                    curr = peek.right;
                }
            }
        }
    }

    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))
        );
        preorderTraversal(root);
    }

    /*
        31 红
        32 黄
        33 橙
        34 蓝
        35 紫
        36 绿
     */
    public static void colorPrintln(String origin, int color) {
        System.out.printf("\033[%dm%s\033[0m%n", color, origin);
    }
}

  复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。每一个节点恰好被遍历一次。
  • 空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为 O(log n),最坏情况下树呈现链状,为 O(n)



力扣题144 二叉树的前序遍历

Leetcode144. 二叉树的前序遍历

/**
 * Definition for a binary tree node.
 * 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;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
		/*
         * 栈
         */
        LinkedList<TreeNode> stack = new LinkedList<>();

        /*
         * 代表当前节点
         */
        TreeNode current = root;
        /*
         * 最近一次弹栈的元素
         */
        TreeNode pop = null;

        List<Integer> result = new ArrayList<>();
        while (!stack.isEmpty() || current != null) {
            if (current != null) {
                stack.push(current);
                // 待处理左子树
                result.add(current.val);
                current = current.left;
            } else {
                TreeNode peek = stack.peek();
                // 没有右子树
                if (peek.right == null) {
                    // 获取最近一次弹栈的元素
                    pop = stack.pop();
                }
                // 右子树处理完成
                else if (peek.right == pop) {
                    // 获取最近一次弹栈的元素
                    pop = stack.pop();
                }
                // 待处理右子树
                else {
                    current = peek.right;
                }
            }
        }
        return result;
    }
}

力扣题94 二叉树的中序遍历

Leetcode94. 二叉树的中序遍历

/**
 * Definition for a binary tree node.
 * 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;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        /*
         * 栈
         */
        LinkedList<TreeNode> stack = new LinkedList<>();

        /*
         * 代表当前节点
         */
        TreeNode current = root;
        /*
         * 最近一次弹栈的元素
         */
        TreeNode pop = null;

        List<Integer> result = new ArrayList<>();
        while (!stack.isEmpty() || current != null) {
            if (current != null) {
                stack.push(current);
                // 待处理左子树
                current = current.left;
            } else {
                TreeNode peek = stack.peek();
                // 没有右子树
                if (peek.right == null) {
                    result.add(peek.val);
                    // 获取最近一次弹栈的元素
                    pop = stack.pop();
                }
                // 右子树处理完成
                else if (peek.right == pop) {
                    // 获取最近一次弹栈的元素
                    pop = stack.pop();
                }
                // 待处理右子树
                else {
                    result.add(peek.val);
                    current = peek.right;
                }
            }
        }
        return result;
    }
}

力扣题145. 二叉树的后序遍历

Leetcode145. 二叉树的后序遍历

/**
 * Definition for a binary tree node.
 * 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;
 *     }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        /*
         * 栈
         */
        LinkedList<TreeNode> stack = new LinkedList<>();
        /*
         * 代表当前节点
         */
        TreeNode current = root;
        /*
         * 最近一次弹栈的元素
         */
        TreeNode pop = null;

        List<Integer> result = new ArrayList<>();
        while (!stack.isEmpty() || current != null) {
            if (current != null) {
                stack.push(current);
                // 待处理左子树
                current = current.left;
            } else {
                TreeNode peek = stack.peek();
                // 没有右子树
                if (peek.right == null) {
                    // 获取最近一次弹栈的元素
                    pop = stack.pop();
                    result.add(pop.val);
                }
                // 右子树处理完成
                else if (peek.right == pop) {
                    // 获取最近一次弹栈的元素
                    pop = stack.pop();
                    result.add(pop.val);
                }
                // 待处理右子树
                else {
                    current = peek.right;
                }
            }
        }
        return result;
    }
}



本文是博主的粗浅理解,可能存在一些错误或不完善之处,如有遗漏或错误欢迎各位补充,谢谢

  如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~


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

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

相关文章

03--数据库连接池

1、数据库连接池 1.1 JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时&#xff0c;传统的模式基本是按以下步骤&#xff1a; 在主程序&#xff08;如servlet、beans&#xff09;中建立数据库连接进行sql操作断开数据库连接 这种模式开发&#xff0c;存在的问题:…

小程序样例2:简单图片分类查看

基本功能&#xff1a; 1、根据分类展示图片&#xff0c;点击类目切换图片&#xff1a; 2、点击分类编辑&#xff0c;编辑分类显示&#xff1a; 3、点击某个分类&#xff0c;控制主页该分类显示和不显示&#xff1a; 类目2置灰后&#xff0c;主页不再显示 4、点击分类跳转到具…

【C++语言1】基本语法

前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;正在学习C&#xff0c;数据结构等&#x1f440; &#x1f493;作者主页&#xff1a;加油&#xff0c;旭杏的主页&#x1f440; ⏩本文收录在&#xff1a;再识C进阶的专栏&#x1…

Python语法进阶——类

Python中的数据类型都属于类。int、str、list都是Python定义好的数据类型类。 print(type(list))#<class type> print(type(list()))#<class list> 一、自定义数据类型 一、语法 class 类名():pass #类名 要求首字母大写 #()可写可省略。 #pass在这里只是用来保证…

推荐IDEA一个小插件,实用性很高!!

插件&#xff1a; Convert YAML and Properties File 由于每个人的开发习惯不同&#xff0c;在开发过程中会遇到各种小细节的问题。今天给大家介绍一个小插件&#xff0c;作用不大&#xff0c;细节很足。 就是properties类型文件和yml文件互相自由转换 解决&#xff1a;…

2023年DevOps国际峰会暨 BizDevOps 企业峰会(DOIS北京站):核心内容与学习收获(附大会核心PPT下载)

随着科技的飞速发展&#xff0c;软件开发的模式和流程也在不断地演变。在众多软件开发方法中&#xff0c;DevOps已成为当下热门的软件开发运维一体化模式。特别是在中国&#xff0c;随着越来越多的企业开始认识到DevOps的价值&#xff0c;这一领域的研究与实践活动日益活跃。本…

计算机网络——运输层(2)暨小程送书

计算机网络——运输层&#xff08;2&#xff09;暨小程送书 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 运输层&#xff08;2&#xff09;TCP/IP对比TCP&#xff08;传输控制协议&#xff09;&#xff1a;IP&#xff08;互联网协议&#xff09;&#xff1a;总结 拥塞…

【设计模式】适配器和桥接器模式有什么区别?

今天我探讨一下适配器模式和桥接模式&#xff0c;这两种模式往往容易被混淆&#xff0c;我们希望通过比较他们的区别和联系&#xff0c;能够让大家有更清晰的认识。 适配器模式&#xff1a;连接不兼容接口 当你有一个类的接口不兼容你的系统&#xff0c;而你又不希望修改这个…

RabbitMQ的安装使用

RabbitMQ是什么&#xff1f; MQ全称为Message Queue&#xff0c;消息队列&#xff0c;在程序之间发送消息来通信&#xff0c;而不是通过彼此调用通信。 RabbitMQ 主要是为了实现系统之间的双向解耦而实现的。当生产者大量产生数据时&#xff0c;消费者无法快速消费&#xff0c;…

公网环境调试本地配置的Java支付宝沙箱环境模拟支付场景

文章目录 前言1. 下载当面付demo2. 修改配置文件3. 打包成web服务4. 局域网测试5. 内网穿透6. 测试公网访问7. 配置二级子域名8. 测试使用固定二级子域名访问 前言 在沙箱环境调试支付SDK的时候&#xff0c;往往沙箱环境部署在本地&#xff0c;局限性大&#xff0c;在沙箱环境…

【Proteus仿真】【51单片机】遥控小风扇设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用数码管显示模块、L298N电机驱动模块、按键、直流电机风扇、红外遥控等。 主要功能&#xff1a; 系统运行后&#xff0c;数码管显示风扇速度档位&a…

【操作系统】实验二 Proc文件系统

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

FluoroQuest抗淬灭试剂盒I 适合载玻片成像,能够提高荧光信号的强度和稳定性

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;FluoroQuestAnti-fading Kit I Optimized for Slide Imaging&#xff0c;FluoroQuest抗淬灭试剂盒I 适合载玻片成像 一、基本信息 产品简介&#xff1a;FluoroQuest抗淬灭试剂盒I 适合载玻片成像能够抑制淬灭效应&a…

unity项目《样板间展示》开发:素材导入与整理

第一章&#xff1a;素材导入与整理 前言一、创建项目文件二、导入素材模型三、素材模型整理四、光源模型管理结语 前言 这次带大家从0到1做一个unity项目&#xff1a;《样板间展示》。 顾名思义&#xff0c;项目内容是展示样板间&#xff0c;即玩家可以与房间中的物体、家具进行…

二维码地址门牌管理系统:智慧城市新篇章

文章目录 前言一、轮播广告位&#xff1a;全面信息传达二、智能化管理&#xff1a;应对挑战三、安全保障&#xff1a;市民隐私优先四、广泛应用&#xff1a;助力城市建设 前言 随着科技的飞速发展&#xff0c;城市的智能化已成不可逆转的趋势。二维码地址门牌管理系统作为新一…

ITSS认证有用吗❓属于gj级证书吗❓

&#x1f525;ITSS由中国电子技术标准化研究院推出&#xff0c;包括“IT 服务工程师”和“IT 服务经理”两种认证。该系列认证符合GB/T 28827.1 的评估和ITSS服务资质升级要求。 &#x1f3af;ITSS是受到gj认可的&#xff0c;在全国范围内对IT服务管理人员从业资格为一的权威的…

linux杀毒软件clamav安装使用

1、下载 在下面地址下载&#xff1a;https://www.clamav.net/downloads 2、安装 clamav-1.2.1.linux.x86_64.rpm放在/home路径。 执行&#xff1a; chmod -R 777 /home/clamav-1.2.1.linux.x86_64.rpm rpm -ivh clamav-1.2.1.linux.x86_64.rpm3、下载病毒库 下载路径&am…

解决element-ui中的el-select选择器无法显示选中内容的问题

问题描述&#xff1a; 排查方法&#xff1a; 检查数据控制台是否报错&#xff0c;无报错 检查change是否触发&#xff0c;会触发 最后开始百度&#xff0c;查看文档 官方文档有这么一段话&#xff0c;就是属性一定要挂载到data上&#xff0c;不然无法检测。 最后解决&#…

K8S的helm

helm的作用 在没有helm之前&#xff0c;deploymen service ingress &#xff0c;helm的作用就是通过打包的方式&#xff0c;把deployment&#xff0c;service&#xff0c;ingress 这些打包在一块&#xff0c;一键式的部署服务&#xff0c;类似yum 官方提供的一个类似于安装仓库…

python|写一个简单的web应用框架

写应用框架需要写底层服务器么? 这个要区分2种情况&#xff0c;如果应用框架&#xff0c;你没有参考WSGI标准&#xff0c;那么在写应用框架之前&#xff0c;你就必须要定义一套属于自己的服务器&#xff0c;当然本文不采取这种方式&#xff0c;专业的事情应该专业的人来做。我…