【数据结构】二叉树 — 经典OJ面试题剖析!!!

news2025/4/22 9:23:42

目录

二叉树相关oj题

1. 检查两颗树是否相同

2. 另一棵树的子树

3. 翻转二叉树

4. 判断一颗二叉树是否是平衡二叉树

5. 对称二叉树

6. 二叉树的构建及遍历

7. 二叉树的层序遍历

8. 判断一棵树是不是完全二叉树

9. 二叉树的最近公共祖先

10. 根据前序与中序遍历序列构造二叉树

11. 根据中序与后序遍历序列构造二叉树

12. 二叉树创建字符串

13. 二叉树前序非递归遍历实现

14. 二叉树中序非递归遍历实现

15. 二叉树后序非递归遍历实现


二叉树的基本知识可以查看上一篇博客【数据结构】二叉树 — 图文并茂,带你领略它的魅力!!!

二叉树所有题都是围绕着遍历进行的。任何一个二叉树,递归的时候一定是先递归到最左边的。 

二叉树相关oj题

1. 检查两颗树是否相同

给你两棵二叉树的根节点p和q编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。100. 相同的树 - 力扣(LeetCode)

比较相同出现的情况:结构上 和 节点值上(val) 两个因素

  1. 一个为空、一个不为空,不相同
  2. 两个都为空,相同
  3. 两个都不为空 不一定,需要判断val是否相同

子问题思路:先判断根节点的可能出现的上面的情况,然后递归判读左树 和 右树的可能出现的情况。

public boolean isSameTree(TreeNode p, TreeNode q) {
    //只要存在结构上的不同直接返回false
    if(p == null && q!= null || p!=null && q == null) {
        return false;
    }
    //上述代码代码走完之后 要么是两个都为空,要么是两个都不为空
    if(p == null && q == null) {
        return true;
    }
    //代码走到这里  两个都不为空,判断值是否一样
    if(p.val != q.val) {
        return false;
    }
    //p != null && q!=null  &&  p.val == q.val;
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
  • 时间复杂度:O(min(m,n)) 访问到的节点数不会超过较小的二叉树的节点数。(较小的二叉树为空就不判断了)
  • 空间复杂度:O(min(m,n)) 递归调用的层数不会超过较小的二叉树的最大高度,最坏情况下,二叉树的高度等于节点数。

2. 另一棵树的子树

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。root 也可以看做它自身的一棵子树。

572. 另一棵树的子树 - 力扣(LeetCode)

问题分析:三种情况

  1. 是不是相同的树
  2. 是不是root的左子树
  3. 是不是root的右子树
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    if(root == null || subRoot == null) {
        return false;
    }
    //1.是不是和根节点相同
    if(isSameTree(root, subRoot)) {
        return true;
    }
    //判断是不是root的左子树
    if(isSubtree(root.left, subRoot)) {
        return true;
    }
    //判断是不是root的右子树
    if(isSubtree(root.right, subRoot)) {
        return true;
    }
    //返回
    return false;
}

//检查两个树是否相同
public boolean isSameTree(TreeNode p, TreeNode q) {
    if(p == null && q != null || p != null && q == null) {
        return false;
    }
    //走到这里,p和q 要么都为空 ,要么都不为空
    if(p == null && q == null) {
        return true;
    }
    //走到这里,p和q 一定都不为空了,比较他们的val值
    if(p.val != q.val) {
        return false;
    }
    //走到这里,p和q都不为空 且val值一样
    return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}

这里注意,如果不判断空root是否为null,下面这种情况就会出现 空指针异常了

  • root树有个S节点,subRoot右T个节点
  • 时间复杂度为:O(S*T)  root 中每个节点都要跟subRoot中的节点就进行比较。判断两颗树是否相同的方法O(N)。
  • 空间复杂度为:O(max(S,T))

3. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。226. 翻转二叉树 - 力扣(LeetCode)

子问题思路:让左树与右树翻转,再让左树的子节点翻转,然后右树的子节点反转。

public TreeNode invertTree(TreeNode root) {
    //空树不翻转直接返回
    if(root == null) {
        return root;
    }
    //这行代码是走到叶子节点,不用交换空的节点了
    if(root.left == null && root.right == null) {
        return root;
    }
    //交换
    TreeNode tmp = root.left;
    root.left = root.right;
    root.right = tmp;

    invertTree(root.left);
    invertTree(root.right);

    return root;
}

4. 判断一颗二叉树是否是平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。110. 平衡二叉树 - 力扣(LeetCode)

平衡二叉树:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1 

子问题思路:判断根节点的左子树与右子树高度差是否平衡,然后再判断左子树节点高度差是否平衡,右节点高度差是否平衡。

//最坏情况下 每个节点 都要求高度
public boolean isBalanced(TreeNode root) {
    if(root == null) {
        return true;
    }
    //先求当前root,左树和右树的高度
    int leftHeight = maxDepth(root.left);
    int rightHeight = maxDepth(root.right);

    return Math.abs(leftHeight - rightHeight) <= 1 
    && isBalanced(root.left) && isBalanced(root.right);
}

//计算二叉树最大深度
public int maxDepth(TreeNode root) {
    //判断该二叉树是否为空树,同时也是递归结束条件
    if (root == null) {
        return 0;
    }
    int leftHeight = maxDepth(root.left);
    int rightHeight = maxDepth(root.right);
    return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
  • 时间复杂度为:O(N^2) 有n个节点每个节点都要求高度(计算高度差),求每个节点求高度的时间复杂度为O(n)。每个节点都要遍历求树的高度,每个节点每次都要调用maxDepth方法。
  • 上述代码有重复高度计算的情况。字节面试:能不能实现时间复杂度O(n)的代码。
  • 求高度的过程当中 就判断是否平衡,如果某个子树不满足平衡,就返回负数。即—边求高度,一边判端平衡的问题。
//最坏情况下 每个节点 都要求高度
public boolean isBalanced(TreeNode root) {
    if(root == null) {
        return true;
    }
    return maxDepth(root) >= 0;
}

public int maxDepth(TreeNode root) {
    //判断该二叉树是否为空树,同时也是递归结束条件
    if (root == null) {
        return 0;
    }
    int leftHeight = maxDepth(root.left);
    if(leftHeight < 0) {
        return -1;
    }
    int rightHeight = maxDepth(root.right);
    if (leftHeight >= 0 && rightHeight >= 0 
    && Math.abs(leftHeight - rightHeight) <= 1) {
        //在这种情况下 才会返回 真是的高度
        return Math.max(leftHeight, rightHeight) + 1;
    } else {
        return -1;
    }
}

5. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。101. 对称二叉树 - 力扣(LeetCode)

  • 判断整颗树是不是轴对称的,就是判断这颗树的左子树 和 这棵树的右子树是不是对称。
  • 如何判断 左子树与右子树对称, 即左子树的左树和右子树的右树与左子树的右树和右子树的左树是否对称。
public boolean isSymmetric(TreeNode root) {
    if(root == null) return true;

    return isSymmetricChild(root.left, root.right);
}

private boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree) {
    if((leftTree == null && rightTree != null) || (leftTree != null && rightTree == null)) {
        return false;
    }
    if(leftTree == null && rightTree == null) {
        return true;
    }
    // root.left != null && root.right != null 判断值是否相同
    if(leftTree.val != rightTree.val) {
        return false;
    }
    return isSymmetricChild(leftTree.left, rightTree.right) 
    && isSymmetricChild(leftTree.right, rightTree.left);
}

6. 二叉树的构建及遍历

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。二叉树遍历_牛客题霸_牛客网

问题分析:这里已经指定了空树的位置,所以根据前序遍历序列可以画出二叉树。

  • 给的前序遍历的字符串,我们也用前序遍历的方式进行解决。
  • 思路:遍历这个字符串根据前序遍历的方式创建二叉树,然后中序遍历打印出即可。
class TreeNode {
    public char val; //数值域
    public TreeNode left;//左子树引用
    public TreeNode right;//右子树引用
    public TreeNode(char val) {
        this.val = val;
    }
}

public class Main {
    public static int i = 0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
        String str = in.nextLine();
        TreeNode root = createTree(str);
        inOrder(root);

        }
    }

    //创建二叉树并返回根节点
    public static TreeNode createTree(String str) {
        //1.遍历字符串str
        /*for(int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
        }*/

        TreeNode root = null;
        if(str.charAt(i) != '#') {
            //2.前序遍历创建二叉树
            root = new TreeNode(str.charAt(i));
            i++; 
            root.left = createTree(str);
            root.right = createTree(str);
        } else {
            //跳过'#'
            i++;
        }
        //3.放回根节点
        return root;
    }

    //中序遍历
    public static void inOrder(TreeNode root) {
        if(root == null) {
            return;
        }
        inOrder(root.left);
        System.out.print(root.val + " ");
        inOrder(root.right);
    }
}
  • 遍历字符串第一时间想到的是 for循环,但是这里需要递归,每次递时字符串总是会从头开始遍历。把 遍历字符串 i 下标变量放到创建树这个方法的外面。
  • 定义为当前类的成员变量 i ,跟着递归的次数增加,每次递归就是想要的字符了。因createTree方法为static修饰的,i 定义的为static 变量。
  • 被static修饰的成员变量只有一份它是和很多对象共享的。但是本题在OJ上只有一个测试用例,所以没有报错。总之慎用。
  • 因为 i 定义的为static 变量,关于多个测试用例调用该方法 i 置为0的问题,可以在每次对象创建使用该方法前把 i 置为 0
  • 还有一种方法,就是当你在读取字符串的时候就把字符串放到队列当中,不需要 i 的值了也可以解决(下面题目中会讲到类似的方法)

  • 注意体会,在递的过程中节点并没有绑定起来,而是在归的过程中才绑定了节点(建立联系)。
  • 一定是先遍历到最左边树的最底层, 然后返回,对节点进行组织。
  • 前序遍历,中序遍历,后序遍历都是一条路线,只是访问根节点的时机不一样。
  • 这里的 i 难道不会越界吗? 不会。因为给的是先序字符串一定是合法的,符合前序遍历规则的。
  • 即递归的次数是一定的,回溯的次数也是一定的,递归与回溯的次数一定是一样的。

7. 二叉树的层序遍历

层序遍历:从上到下,从左到右,依次遍历。

  • 从上到下:前序,中序,后序本质上都是从上到下。
  • 从左到右:创建一个队列实现。

第一种方法:无返回值要求

思路:用非递归的方式(也可以用递归的方式写)。创建一个队列,放二叉树的根节点,当队列不为空时出队列,记录并打印这个节点,然后放左子树,右子树。过程一定是先入左后入右。

public void levelOrder2(TreeNode root) {
    if (root == null) {
        return;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while(!queue.isEmpty()) {
        TreeNode cur = queue.poll();
        System.out.print(cur.val + " ");
        if(cur.left != null) {
            queue.offer(cur.left);
        }
        if (cur.right != null) {
            queue.offer(cur.right);
        }
    }
}

第二种方法:有返回值要求。102. 二叉树的层序遍历 - 力扣(LeetCode)

  • 问题分析:需要确定每一层有哪些以及多少个节点
  • 思路:记录队列中元素个数,来确定每层元素的个数 ,将每层的元素都放到一个数组中,然后再将每个数组的第一个元素都放到一个数组中。
public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> ret = new ArrayList<>();
    if (root == null) {
        return ret;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);

    while(!queue.isEmpty()) {
        int size = queue.size();
        List<Integer> tmp = new ArrayList<>();
        
        //记录队列中元素个数,来确定每层的元素个数
        while (size != 0) {
            TreeNode cur = queue.poll();
            //System.out.print(cur.val + " ");
            tmp.add(cur.val);
            size--;

            if(cur.left != null) {
                queue.offer(cur.left);
            }
            if (cur.right != null) {
                queue.offer(cur.right);
            }
        }
        ret.add(tmp);
    }
    return ret;

}

拓展:阿里的面试题:输出一颗二叉树的左视图(从左边看),即数组每层的第一个节点。

右视图,即数组每层的最后一个节点。

8. 判断一棵树是不是完全二叉树

利用层序遍历的思路:

// 判断一棵树是不是完全二叉树
boolean isCompleteTree(TreeNode root) {
    if (root == null) {
        return true;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);

    while (!queue.isEmpty()) {
        TreeNode cur = queue.poll();
        if (cur != null ) {
            queue.offer(cur.left);
            queue.offer(cur.right);
        } else {
            break;//结束这个循环
        }
    }
    //代码走到这里队列一定不为空,因为null同样入队了
    //需要判断队列当中 是否有非空元素
    while (!queue.isEmpty()) {
        //一个元素一个元素 出队列判断 是不是空
        if (queue.poll() != null) {
            return false;
        }
    }
    return true;
}

9. 二叉树的最近公共祖先

给定一个二叉树,找到该树中两个指定节点的最近公共祖先。

最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”其中p和q 均存在。236. 二叉树的最近公共祖先 - 力扣(LeetCode)

第一种方法:

问题分析:

p 和 q 在根的左右两边

都在根的左边 或者 右边

其中一个节点是公共祖先

还有一种情况,根节点root 是p或者q其中一个,如果是其中一个则公共节点就是它,跟上面的 其中一个节点是公共节点情况一样

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null) {
        return null;
    }
    if (root == p || root == q) {
        return root;
    }
    TreeNode leftTree = lowestCommonAncestor(root.left, p,q);
    TreeNode rightTree = lowestCommonAncestor(root.right, p,q);

    if (leftTree != null && rightTree != null) {
        return root;
    } else if (leftTree != null) {
        return leftTree;
    } else {
        return rightTree;
    }
}

第二种方法: 利用栈来做

  • 二叉树目前来说不能这样做,因为没有父节点地址;可以使用数据结构,用两个栈。
  • 谁多谁先走差值个,s2先弹出1个,然后s1与s2 一起一个一个弹,比较是否相同,相同就是公共祖先。
  • 如何从根节点到指定节点,找到路径上的所有节点,放到栈里面
  • 回溯的时候弹出去,怎么知道当前这个节点要弹出去?

10. 根据前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
题目给有
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列
所以不用判断二叉树为空、以及遍历的序列是否合法的情况等

问题分析:

  1. 根据前序遍历,找到根
  2. 在中序遍历当中,找到根的位置 ri

以前序遍历的方式递归,递归在回溯的时候才把二叉树给串起来。

11. 根据中序与后序遍历序列构造二叉树

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

  • 根据后序遍历序列找根节点
  • 跟上面的代码差不多一样,只不过是从后往前遍历中序遍历序列,然后创建根,创建右树,再创建左树

12. 二叉树创建字符串

给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。

空节点使用一对空括号对 "()" 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。606. 根据二叉树创建字符串 - 力扣(LeetCode)

13. 二叉树前序非递归遍历实现

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。144. 二叉树的前序遍历 - 力扣(LeetCode)

问题分析:非递归root是不会变的,我们需要创建cur代替root,利用栈(先进后出)模拟递归来解决问题。

public void preOrderNor(TreeNode root) {
    if (root == null) {
        return;
    }
    Deque<TreeNode> stack = new ArrayDeque<>();
    TreeNode cur = root;

    while (cur != null || !stack.isEmpty()) {
        while (cur != null) {
            stack.push(cur);
            System.out.print(cur.val + " ");
            cur = cur.left;//cur往左走
        }
        TreeNode top = stack.pop();
        cur = top.right;
    }
}

注意这里的while(cur != null || !stack.isRmpty()) 条件是反向推出来的。

14. 二叉树中序非递归遍历实现

  1. 一直往左走遇到空停止,左树走完了弹出栈顶元素并且打印。
  2. 遍历弹出节点的右子树
public void inOrderNor(TreeNode root) {
    if (root == null) {
        return;
    }
    Deque<TreeNode> stack = new ArrayDeque<>();
    TreeNode cur = root;

    while (cur != null || !stack.isEmpty()) {
        while (cur != null) {
            stack.push(cur);
            cur = cur.left;
        }

        TreeNode top = stack.pop();
        System.out.print(top.val + " ");
        cur = top.right;
    }
}

 

15. 二叉树后序非递归遍历实现


好啦Y(^o^)Y,本节内容到此就结束了。下一篇内容一定会火速更新!!!

后续还会持续更新数据结构与算法方面的内容,还请大家多多关注本up,第一时间获取新鲜的知识。

如果觉得文章不错,别忘了一键三连哟!

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

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

相关文章

【MySQL】用户账户、角色、口令、PAM

目录 查看用户账户设置 连接 1.本地连接 2.远程连接 账户 角色 操作用户账户和角色 配置口令和账户有效期限 手工使口令过期 配置口令有效期限 PAM身份验证插件 客户端连接&#xff1a;使用 PAM 账户登录 在连接到MySQL服务器并执行查询时&#xff0c;会验证你的身…

SpringBoot 3+ Lombok日志框架从logback改为Log4j2

r要将Spring Boot 3项目中的日志框架从Logback切换到Log4j2&#xff0c;并配置按日期滚动文件和控制台输出&#xff0c;请按照以下步骤操作&#xff1a; 步骤 1&#xff1a;排除Logback并添加Log4j2依赖 在pom.xml中修改依赖&#xff1a; <dependencies><!-- 排除默…

【Tauri2】002——Cargo.toml和入口文件

目录 前言 正文 toml文件的基础 注释——# Comment 键值对——Key/Value 表——[table] 内联表——Inline Table 数组——Array package和crate Cargo.toml文件 Cargo.toml——dependencies Cargo.toml——lib crate-type main.rs 前言 【Tauri2】001——安装及…

二叉树相关算法实现:判断子树与单值二叉树

目录 一、判断一棵树是否为另一棵树的子树 &#xff08;一&#xff09;核心思路 &#xff08;二&#xff09;代码实现 &#xff08;三&#xff09;注意要点 二、判断一棵树是否为单值二叉树 &#xff08;一&#xff09;核心思路 &#xff08;二&#xff09;代码实现…

CSS 美化页面(一)

一、CSS概念 CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种用于描述 HTML 或 XML&#xff08;如 SVG、XHTML&#xff09;文档 样式 的样式表语言。它控制网页的 外观和布局&#xff0c;包括字体、颜色、间距、背景、动画等视觉效果。 二、CS…

23种设计模式-组合(Composite)设计模式

组合设计模式 &#x1f6a9;什么是组合设计模式&#xff1f;&#x1f6a9;组合设计模式的特点&#x1f6a9;组合设计模式的结构&#x1f6a9;组合设计模式的优缺点&#x1f6a9;组合设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是组合设计模式…

LSTM创新点不足?LSTM + Transformer融合模型引领Nature新突破

LSTM创新点不足&#xff1f;LSTM Transformer融合模型引领Nature新突破 2024年LSTM真的没有创新空间了吗&#xff1f; 最新研究表明&#xff0c;通过将LSTM与Transformer巧妙融合&#xff0c;依然能创造出Nature级别的突破性成果。LSTM擅长处理短期时序模式&#xff0c;但在…

【区块链安全 | 第六篇】NFT概念详解

文章目录 NFTNFT&#xff08;非同质化代币&#xff09;FT&#xff08;可替代代币&#xff09; 以太坊 NFT 标准ERC-721&#xff08;单一资产&#xff09;ERC-1155&#xff08;多资产&#xff09; NFT 市场版税机制NFT 借贷NFT 安全 NFT NFT&#xff08;Non-Fungible Token&…

iOS常见网络框架

URLSession、Alamofire 和 Moya 1. URLSession 1.1 核心概念 URLSession 是 Apple 官方提供的网络请求 API&#xff0c;封装在 Foundation 框架中。它支持 HTTP、HTTPS、FTP 等协议&#xff0c;可用于&#xff1a; ​ • 普通网络请求&#xff08;GET/POST&#xff09; ​ …

蓝桥杯备考---->激光炸弹(二维前缀和)

本题我们可以构造二维矩阵&#xff0c;然后根据题意&#xff0c;枚举所有边长为m的正方形&#xff0c;找到消灭价值最多的炸弹 #include <iostream> using namespace std; const int N 1e4; int a[N][N]; int n,m; int f[N][N]; int main() {cin >> n >> m…

数据结构 --树和森林

树和森林 树的存储结构 树的逻辑结构 树是一种递归定义的数据结构 树是n(n≥0)个结点的有限集。当n0时&#xff0c;称为空树。在任意一棵非空树中应满足&#xff1a; 1)有且仅有一个特定的称为根的结点。 2)当n>1时&#xff0c;其余结点可分为m(m>0)个互不相交的有…

QOpenGLWidget视频画面上绘制矩形框

一、QPainter绘制 在QOpenGLWidget中可以绘制&#xff0c;并且和OpenGL的内容叠在一起。paintGL里面绘制完视频后&#xff0c;解锁资源&#xff0c;再用QPainter绘制矩形框。这种方式灵活性最好。 void VideoGLWidget::paintGL() {glClear(GL_COLOR_BUFFER_BIT);m_program.bi…

Linux系统加固笔记

检查口令为空的账户 判断依据&#xff1a;存在则不符合 特殊的shell a./bin/false:将用户的shell设置为/bin/false&#xff0c;用户会无法登录&#xff0c;并且不会有任何提示信息b./sbib/nologin&#xff1a;nologin会礼貌的向用户发送一条消息&#xff0c;并且拒绝用户登录…

【Go万字洗髓经】Golang中sync.Mutex的单机锁:实现原理与底层源码

本章目录 1. sync.Mutex锁的基本用法2. sync.Mutex的核心原理自旋到阻塞的升级过程自旋CAS 饥饿模式 3. sync.Mutex底层源码Mutex结构定义全局常量Mutex.Lock()方法第一次CAS加锁能够成功的前提是&#xff1f;竞态检测 Mutex.lockSlow()lockSlow的局部变量自旋空转state新值构造…

Django REST framework 源码剖析-认证器详解(Authentication)

Django REST framework 源码剖析-认证器详解(Authentication) 身份验证始终在视图的最开始运行&#xff0c;在权限和限制检查发生之前&#xff0c;以及在允许任何其他代码继续之前。request.user属性通常设置为contrib.auth包的user类的实例。request.auth属性用于任何其他身份…

TCP/IP三次握手的过程,为什么要3次?

一&#xff1a;过程 第一次&#xff08;SYN&#xff09;&#xff1a; 客户端发送一个带有SYN标志的TCP报文段给服务器&#xff0c;设置SYN1&#xff0c;并携带初始序列号Seqx&#xff08;随机值&#xff09;&#xff0c;进入SYN_SENT状态。等待服务器相应。 第二次&#xff08…

Centos6安装nerdctl容器运行时

Centos6安装nerdctl容器运行时 前言Centos6安装docker---失败--不可拉取镜像docker配置国内镜像加速 Centos6安装nerdctl-full容器管理工具为Centos6配置containerd服务开机自启动设置nerdctl自动补全 前言 本文写于2025年3月22日,因一些特殊业务需要用到Centos6Docker,但Cent…

登录验证码的接口实习,uuid,code.

UID是唯一标识的字符串,下面是百度百科关于UUID的定义&#xff1a; UUID是由一组32位数的16进制数字所构成&#xff0c;是故UUID理论上的总数为16322128&#xff0c;约等于3.4 x 10^38。也就是说若每纳秒产生1兆个UUID&#xff0c;要花100亿年才会将所有UUID用完。 UUID的标准…

用fofa语法搜索漏洞

FOFA是一款非常强大的搜索引擎 关于对于fofa的描述是&#xff1a;FOFA&#xff08;网络空间资产检索系统&#xff09;是世界上数据覆盖更完整的IT设备搜索引擎&#xff0c;拥有全球联网IT设备更全的DNA信息。 探索全球互联网的资产信息&#xff0c;进行资产及漏洞影响范围分析…

20242817李臻《Linux⾼级编程实践》第6周

20242817李臻《Linux⾼级编程实践》第6周 一、AI对学习内容的总结 Linux进程间通信&#xff08;IPC&#xff09; 1. 进程间通信基本概念 作用: 数据传输&#xff1a;进程间传递数据&#xff08;字节到兆字节级别&#xff09;。共享数据&#xff1a;多个进程操作同一数据&…