数据结构之初始二叉树(4)

news2024/11/26 10:00:46

找往期文章包括但不限于本期文章中不懂的知识点:

个人主页:我要学编程(ಥ_ಥ)-CSDN博客

所属专栏:数据结构(Java版)

二叉树的基本操作

二叉树的相关刷题(上)通过上篇文章的学习,我们简单的了解了二叉树的相关操作。接下来就是有关二叉树的经典题型练习。

二叉树的相关刷题(上)

上一篇也是有关二叉树的经典题型。沿着上篇接着开始学习。

目录

二叉树的前序遍历

二叉树的层序遍历

二叉树的层序遍历 II

从前序与中序遍历序列构造二叉树

二叉树的最近公共祖先

根据二叉树创建字符串


二叉树的前序遍历

题目:

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

输入:root = [1,null,2,3]
输出:[1,2,3]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

示例 5:

输入:root = [1,null,2]
输出:[1,2]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

这个题目如果用递归去做那就比较简单了,但是现在我们要采用非递归的方法来写。

思路:利用栈,将遍历到的所有根结点都入栈(以前序遍历的路线去走) ,并且将这些节点都放入List当中。当遇到 null 时,就开始出栈顶的元素,并且以栈顶元素的 right 指针来重新遍历这棵树,直至栈为空即可。

代码实现:

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new LinkedList<>();
        if (root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        // 因为第一次时,这个循环进不来,所以就加了 cur != null 这个条件
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                // 根结点
                stack.push(cur);
                list.add(cur.val);
                // 左子树
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            // 右子树
            cur = top.right;
        }
        return list;
    }
}

既然前序遍历的代码出来了,那么中序遍历和后序遍历也就可以搞定了。

中序遍历:

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new LinkedList<>();
        if (root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                // 左子树
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            // 根结点
            list.add(top.val);
            // 右子树
            cur = top.right;
        }
        return list;
    }
}

后序遍历:

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new LinkedList<>();
        if (root == null) { 
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        TreeNode prev = null; // 记录添加的前一个位置(防止死循环)
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            // 注意这里不能是pop,因为我们不能确定这个节点的右边是否还有节点
            TreeNode top = stack.peek();
            // 如果右边还有元素,那就得去遍历它;否则,就打印(左为null,右也为null)
            if (top.right == null || top.right == prev) { // 右边被处理过才能进来
                list.add(top.val);
                prev = stack.pop(); // 更新为前一个位置的值 
            } else {
                cur = top.right;
            }
        }
        return list;
    }
}

 总结:其实只要我们知道遍历的顺序,从遍历顺序去解决,那么这种题目就迎刃而解了。

二叉树的层序遍历

题目:

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000] 内
  • -1000 <= Node.val <= 1000

思路:通过队列来存储树中的节点,先储存根结点,再把根结点出队,判断左右子树是否为空,来使其入队。 

代码实现:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new LinkedList<>();
        // 通过队列进行层序遍历
        if (root == null) {
            return ret;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> list = new LinkedList<>();
            // 记录每一层的个数
            int size = queue.size();    
            // 先把每一层的节点都放到list中
            while (size-- > 0) {
                TreeNode cur = queue.poll();
                list.add(cur.val);
                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            // 再把每一层的list放到总的ret中
            ret.add(list);
        }
        return ret;
    }
}

刚刚我们是从上往下遍历这棵树的,现在如果让我们从下往上遍历这棵树呢?

二叉树的层序遍历 II

题目:

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000] 内
  • -1000 <= Node.val <= 1000

思路:从上往下我们已经知道了该怎么遍历,但是从下往上不知道该从何下手?这是我们就可以采用换汤不换药的方法了。即将从上到下的遍历结果储存起来,然后再交换两者的值即可。这样我们最终得到的值就是从下往上遍历的结果了。

代码实现:

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> ret = new LinkedList<>();
        if (root == null) {
            return ret;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            List<Integer> list = new LinkedList<>();
            int size = queue.size();
            while (size-- > 0) {
                TreeNode cur = queue.poll();
                list.add(cur.val);
                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            ret.add(list);
        }
        // 现在ret中是按照从上往下的顺序存储的,我们需要的刚好相反,即需要交换
        swap(ret);
        return ret;
    }

    private void swap(List<List<Integer>> ret) {
        int left = 0;
        int right = ret.size()-1;
        while (left < right) {
            // 交换
            List<Integer> tmp = ret.get(left);
            ret.set(left, ret.get(right));
            ret.set(right, tmp);
            left++;
            right--;
        }
    }
}

还有一种实现方式:就是在插入时,我们不采用尾插的方式,采用头插的方式去构建LIst。

// 采用头插的方式
ret.addFirst(list);

前序遍历、中序遍历、后续遍历的迭代版实现和层序遍历的实现所用的数据结构不同的原因:

不管是前序遍历、中序遍历还是后序遍历,都是左子树的遍历顺序在前,右子树的遍历顺序在后,这就导致了一个问题:如果根结点找不到了(先打印了,就出队列了),那么怎么去找右子树呢?因此我们的需求就是把二叉树的根结点存储起来,即让其最后再出去。这个的效果就是先进后出——> 栈 ;而层序遍历就没有这样的需求了,即从上往下、从左往右依次遍历打印,那么我们打印完这一层的节点之后,就可以舍弃它们了。即先进先出——>队列。

前面我们学习了给了前序和中序遍历或者后续和中序遍历,来构建二叉树,现在我们就用代码来实现一下: 

从前序与中序遍历序列构造二叉树

题目: 

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder 和 inorder 均 无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

思路:与我们做选填是一样的。通过前序遍历来确定二叉树的根结点,再通过根结点在中序遍历中的位置来确定左子树和右子树,而前序遍历往后,就是左子树的根结点,再确定在中序遍历中的位置来确定左子树的根结点的左子树和右子树。一直这样递归下去,直至左子树的下标大于右子树的下标(在中序遍历中) 。

代码实现: 

class Solution {
    // 创建一棵二叉树,先创建根结点,再创建左子树和右子树
    // 根结点就是根据前序遍历来找,
    // 左子树和右子树都是根据前序遍历和中序遍历来找出左子树和右子树的根结点
    private int rootIndex;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        
        return buildTreeChild(preorder, inorder, 0, inorder.length-1);
    }

    private TreeNode buildTreeChild(int[] preorder, int[] inorder, 
    int inorderbegin, int inorderend) {
        // 空树
        if (inorderbegin > inorderend) {
            return null;
        }
        // 创建根结点
        TreeNode root = new TreeNode(preorder[rootIndex]);
        // 找到边界
        int border = findVal(inorder, preorder[rootIndex]);
        rootIndex++;
        // 创建左子树
        root.left = buildTreeChild(preorder, inorder, inorderbegin, border-1);
        // 创建右子树
        root.right = buildTreeChild(preorder, inorder, border+1, inorderend);
        return root;
    }
       
    // 找到根结点在中序遍历中的位置来划分左子树和右子树
    private int findVal(int[] inorder, int val) {
        for (int i = 0; i < inorder.length; i++) {
            if (inorder[i] == val) {
                return i;
            }
        }
        return -1;
    }
}

前序学完了,还有后序:

从中序与后序遍历序列构造二叉树

思路:后序遍历同样是确定根结点的位置,从后序遍历数组的末尾开始遍历根节点,在中序遍历中寻找到根结点的位置并划分左右子树。与上述思路类似。

注意:后序遍历是:左子树 右子树 根;而前序遍历是:根 左子树 右子树 。这也就意味着前序遍历找到的根是左子树的根(除祖先节点外) ,即我们先得创建左子树;而后序遍历找到的根是右子树的根(除祖先节点外),即我们先得创建右子树。因为创建二叉树其实就是依赖于根结点,谁于根结点临近创建谁。

class Solution {
    // 后续遍历找到根结点,再根据根结点确定左子树和右子树
    private int rootIndex;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        rootIndex = postorder.length-1;
        return buildTreeChild(inorder, postorder, 0, inorder.length-1);
    }

    private TreeNode buildTreeChild(int[] inorder, int[] postorder,
    int inorderbegin, int inorderend) {
        if (inorderbegin > inorderend) {
            return null;
        }
        TreeNode root = new TreeNode(postorder[rootIndex]);
        // 在中序遍历的数组中找到根结点的位置
        int border = findVal(inorder, postorder[rootIndex]);
        rootIndex--;
        root.right = buildTreeChild(inorder, postorder, border+1, inorderend);
        root.left = buildTreeChild(inorder, postorder, inorderbegin, border-1);
        return root;
    }

    private int findVal(int[] inorder, int val) {
        for (int i = 0; i < inorder.length; i++) {
            if (inorder[i] == val) {
                return i;
            }
        }
        return -1;
    }
}

二叉树的最近公共祖先

题目: 

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

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 1:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。

示例 2:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。

示例 3:

输入:root = [1,2], p = 1, q = 2
输出:1

提示:

  • 树中节点数目在范围 [2, 105] 内。
  • -109 <= Node.val <= 109
  • 所有 Node.val 互不相同 。
  • p != q
  • p 和 q 均存在于给定的二叉树中。

思路一:采用穷举的方法,看看会出现几种情况。

上面三种情况其实就是通过示例总结出来的 

 代码实现:

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 在递归去寻找的过程中可能会出现下面两种情况(限制条件)
        if (root == null) {
            return null;
        }
        if (root == q || root == p) {
            return root;
        }
        // 走到这里说明根结点一定不存在,则判断左子树和右子树即可
        // 遍历左子树
        TreeNode leftTree = lowestCommonAncestor(root.left, p, q);
        // 遍历右子树
        TreeNode rightTree = lowestCommonAncestor(root.right, p, q);
        // 再遍历完成之后,我们就来判断是哪种情况
        if (leftTree != null && rightTree != null) {
            return root;
        }
        if (leftTree != null && rightTree == null) {
            return leftTree;
        }
        // 下面的代码可以简化为 return rightTree;
        if (leftTree == null && rightTree != null) {
            return rightTree;
        }
        return null;
    }
}

如果我们总结不出来,也没关系。还有另外一种方法,就是把p和q出现的路线储存起来,然后再去一 一比较,遇到第一个相等的就是公共的祖先。

首先,得确定是用什么数据结构来储存路线。栈 还是 队列呢?其实都是可以的。因为我们采用的是从上往下遍历,那么根结点一定是最先被放入栈(队列)中的。而我们比较的方式不同,就导致了储存的方式不同。如果我们是想找不同,那就得用队列,从根结点开始比较;如果我们是想找相同,那就得用栈,从p和q开始比较,找到相同的节点。

栈的实现方式:

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        Stack<TreeNode> stackP = new Stack<>();
        Stack<TreeNode> stackQ = new Stack<>();
        getPath(root, p, stackP);
        getPath(root, q, stackQ);
        // 先让长的走差值步数
        if (stackP.size() > stackQ.size()) {
            int size = stackP.size() - stackQ.size();
            while (size-- > 0) {
                stackP.pop();
            }
        } else {
            int size = stackQ.size() - stackP.size();
            while (size-- > 0) {
                stackQ.pop();
            }
        }
        // 开始一起出
        while (stackQ.peek() != stackP.peek()) {
            stackQ.pop();
            stackP.pop();
        }
        return stackQ.peek();
    }

    private TreeNode getPath(TreeNode root, TreeNode target, Stack<TreeNode> stack) {
        if (root == null) {
            return null;
        }
        stack.push(root); // 先得把这个入栈
        if (root == target) {
            return root;
        }
        // 左子树
        TreeNode leftTree = getPath(root.left, target, stack);
        if (leftTree != null) { // 左子树不为null,说明在左子树找到了,即返回
            return leftTree;
        }
        // 右子树
        TreeNode rightTree = getPath(root.right, target, stack);
        if (rightTree != null) { // 右子树不为null,说明在右子树找到了,即返回
            return rightTree;
        }
        // 左右子树的遍历结果都是null,即都没找到,就出栈
        if (leftTree == null && rightTree == null) {
            stack.pop();
        }
        return null;
    }
}

在用队列去写时,我们就会发现一个问题:如果左右子树都为null,那么证明这个节点不是我们路径上的节点,就得出队,但是队列的数据是先进先出的特点,不满足我们的要求,即普通队列是不行的。因此,就只能用栈。

我们在分析问题时,可能刚刚不会遇到这点,但是后面在做题时,体会到了这点就行,不管是什么思路,我们都得上手去写才可以。

根据二叉树创建字符串

题目:

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

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

示例 1:

输入:root = [1,2,3,4]
输出:"1(2(4))(3)"
解释:初步转化后得到 "1(2(4)())(3()())" ,但省略所有不必要的空括号对后,字符串应该是"1(2(4))(3)" 。

示例 2:

输入:root = [1,2,3,null,4]
输出:"1(2()(4))(3)"
解释:和第一个示例类似,但是无法省略第一个空括号对,否则会破坏输入与输出一一映射的关系。

提示:

  • 树中节点的数目范围是 [1, 104]
  • -1000 <= Node.val <= 1000

思路:根据示例,我们就可以看出:遇到左子树就得添加“(”,当左子树走完,就得添加“)”,当左子树为null,并且右子树不为null时,得添加“()”。 

代码实现:

class Solution {
    // 通过 StringBuild 来构建字符串
    private StringBuilder sb = new StringBuilder();
    public String tree2str(TreeNode root) {
        dfs(root);
        return sb.toString();
    }
    
    private void dfs(TreeNode root) {
        if (root == null) {
            return;
        }
        // 根结点
        sb.append(root.val);
        // 根的左子树
        if (root.left != null) {
            sb.append("(");
            // 继续递归去左子树寻找
            dfs(root.left);
            // 左子树走完了得加右括号
            sb.append(")");
        } else {
            if (root.right != null) {
                // 左边添加一对空括号
                sb.append("()");
            } else {
                return;
            }
        }
        // 根的右子树
        if (root.right != null) {
            sb.append("(");
            dfs(root.right);
            sb.append(")");
        } else {
            return;
        }
    }
}

总结:通过上面几题的练习,我们不难发现其实有的题目需要我们去利用示例的规律来写,但更多的题目是需要我们对数据结构进行不断的学习和熟练,这样才能更加得心应手。 

好啦!本期 数据结构之初始二叉树(4)的学习之旅就到此结束啦!二叉树的折磨也是暂时的结束啦!即将开启新的数据结构之旅!我们下一期再一起学习吧!

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

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

相关文章

基于密钥的身份验证(Linux-Linux)

A主机&#xff1a; 1、生成密钥对 [rootservera ~]# ssh-keygen查看公钥 注&#xff1a;id_rsa为私钥&#xff08;证书&#xff09;&#xff0c;id_rsa.pub为公钥 2、注册公钥到服务器 [rootservera ~]# ssh-copy-id root172.25.250.106 查看.ssh 3、使用密钥连接服务器 #…

ViT(Vision Transformer)网络结构详解

本文在transformer的基础上对ViT进行讲解&#xff0c;transformer相关部分可以看我另一篇博客&#xff08;transformer中对于QKV的个人理解-CSDN博客&#xff09;。 一、网络结构概览 上图展示了Vision Transformer (ViT) 的基本架构&#xff0c;我按照运行顺序分为三个板块进…

配置web服务器

当访问网站www.haha.com时显示&#xff1a;haha&#xff1b;当访问网站www.xixi.com/secret/显示&#xff1a;this is secret 第一步&#xff0c;配置一个新的IP 确认后 esc返回 第二步&#xff1a;重启ens160 第三步&#xff1a;创建目录&#xff0c;并且在文件内写入内容 第…

英福康INFICON UL1000检漏仪介绍PPT

英福康INFICON UL1000检漏仪介绍PPT

【周记】2024暑期集训第二周(未完待续)

文章目录 日常刷题记录合并果子题目解析算法思路代码实现 中位数题目解析算法思路代码实现 C学习笔记队列queue双端队列 deque优先队列 priority_queue定义常见操作 upper_bound 日常刷题记录 合并果子 题目解析 有一堆果子&#xff0c;每次可以将两小堆合并&#xff0c;耗费…

verilog行为建模(四):过程赋值

目录 1.两类过程赋值2.阻塞与非阻塞赋值语句行为差别举例13.阻塞与非阻塞赋值语句行为差别举例24.阻塞与非阻塞赋值语句行为差别举例35.举例4&#xff1a;非阻塞赋值语句中延时在左边和右边的差别 微信公众号获取更多FPGA相关源码&#xff1a; 1.两类过程赋值 阻塞过程赋值执…

漫威争锋Marvel Rivals测试搜不到 漫威争锋Marvel Rivals怎么搜

漫威争锋&#xff0c;一款今年即将上线的6v6的fps游戏&#xff0c;漫威争锋Marvel Rivals一经公布就吸引了广大玩家的兴趣。玩家将在游戏中扮演一名名经典且有趣的漫威英雄&#xff0c;与敌人展开对决。而且该游戏中有着很多的漫威英雄供我们挑选使用&#xff0c;有着很多英雄的…

【数据结构】排序算法——Lessen1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

音乐播放器的优雅之选,黑金ONIX Overture XM5,更悦耳的音质体验

如今想要随时沉浸式的体验高品质的数字音乐资源&#xff0c;一款简单好用的音乐播放器必不可少&#xff0c;多年来在音乐爱好者的心中的经典品牌屈指可数&#xff0c;英国品牌ONIX算是一个&#xff0c;其Horizon系列以优雅的设计以及出众的品质&#xff0c;收获了很多忠实粉丝。…

OpenAI发布迷你AI模型GPT-4o mini

本心、输入输出、结果 文章目录 OpenAI发布迷你AI模型GPT-4o mini前言OpenAI发布迷你AI模型GPT-4o mini英伟达联合发布 Mistral-NeMo AI 模型:120 亿参数、上下文窗口 12.8 万个 tokenOpenAI发布迷你AI模型GPT-4o mini 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csd…

【ADRC笔记】LESO-Wb

公式推导(bilibili) 一阶ESO 二阶ESO 二阶自抗扰控制器基本原理 选取状态变量 观测器收敛性推导 wo 观测器带宽

C语言·函数(超详细系列·全面总结)

前言&#xff1a;Hello大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;为了更好地形成一个学习c语言的体系&#xff0c;最近将会更新关于c语言语法基础的知识&#xff0c;今天更新一下函数的知识点&#xff0c;我们一起来看看吧&#xff01; 目录 一、函数是什么 &a…

HTTPServer改进思路1

Nginx源码思考项目改进 架构模式 事件驱动架构(EDA&#xff09;用于处理大量并发连接和IO操作 优点&#xff1a;高效处理大量并发请求&#xff0c;减少线程切换和阻塞调用技术实现&#xff1a;直接使用EPOLL&#xff0c;参考Node.js的http服务器 网络通信 协议&#xff1a;HTT…

day6 io线程

获取终端输入的字符

记录 cocos 开发问题 ,微信 wx.xxx函数 报找不到名称“wx”

今天写微信排行榜遇到 问题分享一下。 目前&#xff0c;微信、百度 和 抖音 小游戏这些平台为了保护其社交关系链数据&#xff0c;增加了 开放数据域 的概念&#xff0c;这是一个单独的游戏执行环境。开放数据域中的资源、引擎、程序&#xff0c;都和主游戏&#xff08;主域&a…

【2】Spring Cloud 工程搭建

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;Spring Cloud实战&#x1f4d5;格言&#xff1a;吾愚多不敏&#xff0c;而愿加学欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 1.声明项目依赖和项目构建插件 2.完善子项目订单服务 2.1完善启动…

[Spring] Spring配置文件

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

Spring推出Spring AI框架,看看怎么个事

文章目录 概述SpringAI介绍Spring AI 提供以下功能支持的聊天模型有哪些支持的文生图的模型有哪些支持的音频到文本模型支持的嵌入模型有哪些支持的矢量数据库有哪些 概述 在当今快速发展的技术时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为各行各业的关键驱动…

Linux——awk操作符

[rootlocalhost ~] # awk BEGIN{x2;y3;print x**y,x^y,x*y,x/y,xy,x-y,x%y} 8 8 6 0 .666667 5 -1 2 赋值运算符 条件运算符 awk 中的条件运算符只有一个&#xff0c;其语法如下&#xff1a; expression?value1:value2 这是一个三目运算符&#xff0c;当表达式 expre…

#三元运算符(python/java/c)

引入&#xff1a;什么是三元运算符呢&#xff1f;无疑其操作元有三个&#xff0c;一个是条件表达式&#xff0c;剩余两个为值&#xff0c;条件表达式为真时运算取第一个值&#xff0c;为假时取第二个值。 一 Python true_expression if condition else false_expressi…