Day9 25/2/22 SAT

news/2025/2/23 15:17:05

【一周刷爆LeetCode,算法大神左神(左程云)耗时100天打造算法与数据结构基础到高级全家桶教程,直击BTAJ等一线大厂必问算法面试题真题详解(马士兵)】https://www.bilibili.com/video/BV13g41157hK?p=4&vd_source=04ee94ad3f2168d7d5252c857a2bf358

目录

5、二叉树

5.0 二叉树节点结构

5.1 前序/中序/后序遍历 & 递归/非递归实现

5.1.1 前序/中序/后序遍历区分

5.1.2 递归实现

5.1.3 非递归实现

5.2 直观地打印一棵二叉树

5.3 二叉树的宽度优先遍历

5.4 二叉树类型判断

二叉搜索树

完全二叉树

真二叉树

满二叉树

平衡二叉树


笔记:

5、二叉树

5.0 二叉树节点结构

class Node<V>{
    V calue;
    Node left;
    Node right;
}

5.1 前序/中序/后序遍历 & 递归/非递归实现

5.1.1 前序/中序/后序遍历区分

在二叉树中,遍历的顺序指的是访问节点的顺序:

前序遍历(Pre-order Traversal):根节点 -> 左子树 -> 右子树。

中序遍历(In-order Traversal):左子树 -> 根节点 -> 右子树。

后序遍历(Post-order Traversal):左子树 -> 右子树 -> 根节点。

主要区别在于根节点的访问时机:

前序遍历最先访问根节点。

中序遍历,根节点在左右子树都访问完成后才被访问。

后序遍历最后访问根节点。

5.1.2 递归实现

class Node<V>{
    V calue;
    Node left;
    Node right;
}

// 前序遍历
public void preOrder(Node root) {
    if (root == null) return;
    System.out.print(root.val + " ");  // 先访问根节点
    preOrder(root.left);               // 再遍历左子树
    preOrder(root.right);              // 最后遍历右子树
}

// 中序遍历
public void inOrder(Node root) {
    if (root == null) return;
    inOrder(root.left);                // 先遍历左子树
    System.out.print(root.val + " ");  // 再访问根节点
    inOrder(root.right);               // 最后遍历右子树
}

//后序遍历
public void postOrder(Node root) {
    if (root == null) return;
    postOrder(root.left);              // 先遍历左子树
    postOrder(root.right);             // 再遍历右子树
    System.out.print(root.val + " ");  // 最后访问根节点
}

5.1.3 非递归实现

任何递归函数都可以改成非递归函数,相当于不让系统自动压入栈,而是自己手动压入栈。栈是先进后出的。

前序遍历中,遍历顺序为“头左右”(头节点、左子节点、右子节点),操作:

step 1. 从栈中弹出一个节点N

step 2. 找到它的左、右子节点

step 3. 先压入栈右子节点,再压入左子节点(这样先弹出左子节点,再弹出右子节点)

public static void preorder(Node node){
    if(node != null){
        Stack<Node> stack = new Stack<Node>();
        stack.add(node);

        while( !stack.isEmpty() ){
            node = stack.pop();
            System.out.print(node.value + “ ”);
            if( node.right != null)stack.push(node.right);
            if( node.left != null)stack.push(node.left);
        }
    }
}

中序遍历中,遍历顺序为“左头右”(左子节点、头节点、右子节点),操作:

public static void inorder(Node node){
    if(node != null){
        Stack<Node> stack = new Stack<Node>();
        while( !stack.isEmpty() || node != null ){
            if( node != null){
                stack.push(node);
                node = node.left;
            }else{
                node = stack.pop();
                System.out.print(node.value + “ ”);
                node = node.right;
            }
        }
    }
}

后序遍历中,遍历顺序为“左右头”(左子节点、右子节点、头节点),操作:

public static void postorder(Node node){
    if(node != null){
        Stack<Node> s1 = new Stack<Node>();
        Stack<Node> s2 = new Stack<Node>();
        s1.push(node);
        
        while( !s1.isEmpty() ){
            node = s1.pop();
            s2.push(node);
            if( node.left!= null)s1.push(node.left);
            if( node.right!= null)s1.push(node.right);
        }
        while( !s2.isEmpty() ) System.out.print(s2.pop().value + “ ”);
    }
}

5.2 直观地打印一棵二叉树

class BinaryTreePrinter {
    // 打印二叉树的结构
    static void printTree(TreeNode root) {
        printTree(root, "", true);
    }

    // 辅助方法:递归打印每层节点
    private static void printTree(TreeNode node, String indent, boolean last) {
        if (node != null) {
            System.out.println(indent + (last ? "└── " : "├── ") + node.val);
            indent += last ? "    " : "│   ";
            printTree(node.left, indent, false);  // 打印左子树
            printTree(node.right, indent, true);  // 打印右子树
        }
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        root.right.left = new TreeNode(6);
        root.right.right = new TreeNode(7);
        
        printTree(root);
    }
}

5.3 二叉树的宽度优先遍历

常见题目:求一颗二叉树的宽度,也就是树的每层最多存在了几个节点。

可以采用队列Queue进行辅助,队列的特性是先进先出。遍历完一层后要遍历下一层的节点时,每次弹出一个节点,再把它的左右子节点推进队列。

public static void broadReversal(Node node) {
        if (node == null) return;

        Queue<Node> queue = new LinkedList<>();
        queue.add(node);

        int maxWidth = 0;

        // 广度优先遍历
        while (!queue.isEmpty()) {
            // 获取当前层的节点数
            int levelSize = queue.size();
            maxWidth = Math.max(maxWidth, levelSize); // 更新最大宽度

            // 遍历当前层
            for (int i = 0; i < levelSize; i++) {
                Node current = queue.poll();
                System.out.print(current.value + " "); // 输出当前节点的值

                // 将左右子节点加入队列
                if (current.left != null) queue.add(current.left);
                if (current.right != null) queue.add(current.right);
            }
            System.out.println(); // 换行,表示一层的结束
        }

        System.out.println("Maximum width of the binary tree is: " + maxWidth);
    }

5.4 二叉树类型判断

与一个节点直接连接的子节点数,也叫“度数”。

度数为0即没有左右节点,度数为1则只有左节点或右节点,度数为2

二叉搜索树

是一类二叉树,左子树的key都小于当前节点的key、右子树的key都大于当前节点的key

完全二叉树

是一类二叉树,叶子节点只会出现在最后两层(最后一层可能不是满的),且最后一层的叶子节点都靠左对齐 特点:完全二叉树从root到倒数第二层是一棵满二叉树; 度数为1的节点只有左子树;

真二叉树

是一类二叉树,所有节点的度要么为0要么为2。

满二叉树

是一类二叉树,每一层都是满的,而且叶子节点都在同一层上。

平衡二叉树

每个节点都有一个平衡因子(balance factor)来确保树的高度始终保持在一个较小的范围内,从而保证查询、插入和删除操作的时间复杂度始终为O(logn)

性质:所有操作的时间复杂度都为O(logn)

①左右子节点的高度差的绝对值不超过1(the children of a node can differ by at most 1)

②左小右大

③height-balance  高度是平衡的

应用场景:适用于需要严格保证操作时间的场景(比如数据库搜索)


http://www.niftyadmin.cn/n/5863521.html

相关文章

MTK-Android13-包安装器PackageInstaller 静默安装实现

目的 我们最终是为了搞明白安装的整个流程。一方面通过安卓系统自带的包安装器来了解PMS 安装流程&#xff1b;另一方面熟悉框架层Framework 针对Android apk 安装流程。 前两篇文章分析了PackagerInstaller 安装流程。 Android13-包安装器PackageInstaller-之apk安装跳转 An…

C++:dfs,bfs各两则

1.木棒 167. 木棒 - AcWing题库 乔治拿来一组等长的木棒&#xff0c;将它们随机地砍断&#xff0c;使得每一节木棍的长度都不超过 5050 个长度单位。 然后他又想把这些木棍恢复到为裁截前的状态&#xff0c;但忘记了初始时有多少木棒以及木棒的初始长度。 请你设计一个程序…

力扣-贪心-376 摆动序列

思路 记录前一个差值和后一个差值&#xff0c;需要分析很多情况 只有在发生波动的时候才更新差值——单调中有平坡前一个差值0时也更新差值——平坡留下最左边元素最后一个元素不记录.默认从最后一个有坡度 代码 class Solution { public:int wiggleMaxLength(vector<in…

企业微信第三方应用开发025_企微通讯录组件使用04_vue中使用ww-open-data通讯录展示组件---企业微信开发027

前面已经调试通了,已经成功了,这里只是给出一个例子,来实现,对ww-open-data的使用 在vue中使用. 首先在: <template><div><el-dialog:close-on-click-modal="false"title="新增员工活码":type="type":visible.sync="dial…

如何有效判断与排查Java GC问题

干货分享&#xff0c;感谢您的阅读&#xff01; 在现代Java应用中&#xff0c;垃圾回收&#xff08;GC&#xff09;是一个不可忽视的重要环节。尽管GC自动管理内存&#xff0c;避免了手动释放资源的麻烦&#xff0c;但它带来的性能开销却常常困扰开发者。从GC暂停时间到吞吐量…

计算机网络-面试总结

计算机网络 从输入一个URL到页面加载完成的过程 整体流程 DNS查询过程SSL四次握手HTTP 的长连接与短连接 HTTP 的 GET 和 POST 区别浏览器访问资源没有响应&#xff0c;怎么排查? OSI七层参考模型 TCP/IP四层参考模型比较 TCP/IP 参考模型与 OSI 参考模型 TCP三次握手&四…

Python 高级数据结构操作全解析:从理论到实践

Python 高级数据结构操作全解析&#xff1a;从理论到实践 本文深入剖析 Python 高级数据结构&#xff0c;通过丰富的代码示例、形象的配图&#xff0c;详细讲解集合、字典、堆、队列等数据结构的操作&#xff0c;同时拓展相关知识&#xff0c;帮助读者深入掌握 Python 编程核心…

吉林大学数据库系统概念SQL、关系代数习题汇总

吉林大学数据库系统概念SQL、关系代数习题汇总(持续更新) 奔腾 数据库系统原理考试&#xff08;A卷&#xff09; // (1) create table branch( branch_name varchar(20), branch_city varchar(20), assets numeric(12, 2), primary key (branch_name));create table customer(…