当前位置: 首页 > news >正文

《Java初阶数据结构》----5.<二叉树的概念及使用>

前言
大家好,我目前在学习java。之前也学了一段时间,但是没有发布博客。时间过的真的很快。我会利用好这个暑假,来复习之前学过的内容,并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区进行讨论!!!
喜欢我文章的兄弟姐妹们可以点赞,收藏和评论我的文章。喜欢我的兄弟姐妹们以及也想复习一遍java知识的兄弟姐妹们可以关注我呦,我会持续更新滴,
望支持!!!!!!一起加油呀!!!!

语言只是工具,不能决定你好不好找工作,决定你好不好找工作的是你的能力!!!!!

学历本科及以上就够用了!!!!!!!!!!!!!!!!!!!!!!

【本章博客包含】
1.树的基本概念
2.二叉树概念及特性
3.二叉树的基本操作及方法模拟实现
4.二叉树相关的编程题练习

一、树的概念

1.1基本概念

是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树。它是根朝上,而叶朝下的。

  • 它具有以下的特点:
  1. 有一个特殊的结点,称为根结点,根结点没有前驱结点
  2. 除根结点外,其余结点被分成M(M > 0)个互不相交的集合T1、T2、…、Tm,其中每一个集合Ti (1 <= i <=m) 又是一棵与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
  3. 树是递归定义的。

//注意:树形结构中,子树之间不能有交集,否则就不是树形结构

1.2内部(重要)概念

在这里插入图片描述

1.结点的度:一个结点含有子树的个数称为该结点的度; 如上图:A的度为6
2.树的度:一棵树中,所有结点度的最大值称为树的度; 如上图:树的度为6
3.叶子结点或终端结点:度为0的结点称为叶结点; 如上图:B、C、H、I…等节点为叶结点
4.双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点
5.孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点
6.根结点:一棵树中,没有双亲结点的结点;如上图:A
7.结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推
8.树的高度或深度:树中结点的最大层次; 如上图:树的高度为4

树的以下概念只需了解,在看书时只要知道是什么意思即可:

非终端结点或分支结点:度不为0的结点; 如上图:D、E、F、G…等节点为分支结点
兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点
堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:H、I互为兄弟结点
结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
森林:由m(m>=0)棵互不相交的树组成的集合称为森林

1.3树的表示形式

双亲表示法,孩子表示法、孩子双亲表示法、孩子兄弟表示法等等。
最常用的:孩子兄弟表示法。

1.4树的应用

文件管理系统(目录和文件)

二、二叉树的概念

2.1概念

一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
    在这里插入图片描述

二叉树特点:
1.二叉树不存在度大于2的结点
2.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

注意:对于任意的二叉树都是由以下几种情况复合而成的:
在这里插入图片描述

2.2两种特殊的二叉树

  1. 满二叉树:一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为K,且结点总数是,则它就是满二叉树。
  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应时称之为完全二叉树。

注意:满二叉树是一种特殊的完全二叉树。
在这里插入图片描述

2.3二叉树的性质

  1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有(i>0)个结点
  2. 若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是(k>=0)
  3. 对任何一棵二叉树,如果其叶结点个数为n0,度为2的非叶结点个数为n2,则有n0=n2+1
  4. .具有n个结点的完全二叉树的深度k为log以2为低(n+1)上取整
  5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有:
  • 若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
  • 若2i+1<n,左孩子序号:2i+1,否则无左孩子
  • 若2i+2<n,右孩子序号:2i+2,否则无右孩子
    优先级队列

性质3的推导
节点:n = n1 + n2 + n3
边:e = 2n2 + n1 = n-1 (除根节点外每个节点对应一条边)
得出 2n2 + n1 = n1 + n2 + n3 -1
化简:n0= n2+ 1

2.4二叉树的存储

二叉树的存储结构分为:顺序存储和类似于链表的链式存储
顺序存储在优先级队列文章介绍。
二叉树的链式存储通过一个一个的节点引用起来的,常见的表示方式有二叉三叉表示方式,具体如下:

// 孩子表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
} // 孩子双亲表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
Node parent; // 当前节点的根节点
}

孩子双亲表示法后序在平衡树位置介绍,本文采用孩子表示法来构建二叉树。

三、二叉树的基本操作

// 前序遍历
void preOrder(Node root);// 中序遍历
void inOrder(Node root);// 后序遍历
void postOrder(Node root);// 获取树中节点的个数
int size(Node root);// 获取叶子节点的个数
int getLeafNodeCount(Node root);
// 子问题思路-求叶子结点个数// 获取第K层节点的个数
int getKLevelNodeCount(Node root,int k);// 获取二叉树的高度
int getHeight(Node root);// 检测值为value的元素是否存在
Node find(Node root, int val);//层序遍历
void levelOrder(Node root);// 判断一棵树是不是完全二叉树
boolean isCompleteTree(Node root);

1.前序遍历

1.1 二叉树无返回值的前序遍历
    //二叉树无返回值的前序遍历public void prevOrder(TreeNode root){if(root == null){return;}System.out.print(root.val+" ");preOrder(root.left);preOrder(root.right);}
1.2 二叉树有返回值的前序遍历
    public List<Character> preorderTraversal(TreeNode root) {List<Character> ret = new ArrayList<>();if(root == null){return ret;}ret.add(root.val);List<Character> leftTree = preorderTraversal(root.left);ret.addAll(leftTree);List<Character> rightTree = preorderTraversal(root.right);ret.addAll(rightTree);return ret;}

2.中序遍历

    public void inOrder(TreeNode root){if (root == null){return;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}
    public List<Character>  inOrderTraversal(TreeNode root){List<Character> ret = new ArrayList<>();if(root == null){return ret;}List<Character> leftTree = inOrderTraversal(root.left);ret.addAll(leftTree);ret.add(root.val);List<Character> rightTree = inOrderTraversal(root.right);ret.addAll(rightTree);return ret;}

3.后序遍历

    //后序遍历public void postOrder(TreeNode root){if (root == null){return;}postOrder(root.left);postOrder(root.right);System.out.print(root.val+" ");}
    public List<Character>  postOrderTraversal(TreeNode root){List<Character> ret = new ArrayList<>();if(root == null){return ret;}List<Character> leftTree = inOrderTraversal(root.left);ret.addAll(leftTree);List<Character> rightTree = inOrderTraversal(root.right);ret.addAll(rightTree);ret.add(root.val);return ret;}

4.获取树中节点个数

    // 获取树中节点的个数public int size;int sizeNode(TreeNode root){if(root == null){return 0;}size++;sizeNode(root.left);sizeNode(root.right);return size;}
    int sizeNode2(TreeNode root){if(root == null){return 0;}return sizeNode2(root.left)+sizeNode2(root.right)+1;}

5.获取叶子节点的个数

    //5. 获取叶子节点的个数(左右都为空)int getLeafNodeCount1(TreeNode root){if(root == null){return 0;}if(root.left == null && root.right == null){return 1;}return getLeafNodeCount1(root.left)+getLeafNodeCount1(root.right);}
    public int leafSize;void getLeafNodeCount2(TreeNode root){if(root == null){return;}if(root.left == null && root.right == null){leafSize++;}getLeafNodeCount2(root.left);getLeafNodeCount2(root.right);}

子问题思路-求叶子结点个数

// 子问题思路-求叶子结点个数int getLeafNodeCount1(TreeNode root){if(root == null){return 0;}if(root.left == null && root.right == null){return 1;}return getLeafNodeCount1(root.left)+getLeafNodeCount1(root.right);}
    //统计求解public int leafSize;void getLeafNodeCount2(TreeNode root){if(root == null){return;}if(root.left == null && root.right == null){leafSize++;}getLeafNodeCount2(root.left);getLeafNodeCount2(root.right);}

6.获取第K层节点的个数

    // 获取第K层节点的个数int getKLevelNodeCount(TreeNode root,int k){if(root == null){return 0;}if(k == 1){return 1;}return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);}

7.获取二叉树的高度

    // 获取二叉树的高度int getHeight(TreeNode root){if(root ==null){return 0;}getHeight(root.left);getHeight(root.right);return Math.max(getHeight(root.left),getHeight(root.right))+1;}
    int getHeight1(TreeNode root){if(root ==null){return 0;}int left = getHeight(root.left);int right = getHeight(root.right);return Math.max(left,right)+1;}
    int getHeight2(TreeNode root){if(root ==null){return 0;}return Math.max(getHeight(root.left),getHeight(root.right))+1;}

8.检测值为value的元素是否存在

    // 检测值为value的元素是否存在boolean findVal(TreeNode root, int val){if(root == null){return false;}if(root.val == val){return true;}boolean leftVal = findVal(root.left,val);if(leftVal){return true;}boolean rightVal = findVal(root.right,val);if(rightVal){return true;}return false;}

9.层序遍历

    //层序遍历(无返回值)public void levelOrder(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);}}}
    //有返回值为List<List<TreeNode>>的层序遍历public List<List<TreeNode>> levelOrder2(TreeNode root){List<List<TreeNode>> ret = new ArrayList<>();if(root == null){return ret;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while (!queue.isEmpty()){int size = queue.size();List<TreeNode> temp = new ArrayList<>();while ((size!=0)){TreeNode cur = queue.poll();temp.add(cur);size--;if(cur.left!=null){queue.offer(cur.left);}if(cur.right!=null){queue.offer(cur.right);}}ret.add(temp);}return ret;}
    //有返回值为List<List<Character>>的层序遍历public List<List<Character>> levelOrder3(TreeNode root) {List<List<Character>> ret = new ArrayList<>();if(root == null){return ret;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);while (!queue.isEmpty()){int size = queue.size();List<Character> temp = new ArrayList<>();while ((size!=0)){TreeNode cur = queue.poll();temp.add(cur.val);size--;if(cur.left!=null){queue.offer(cur.left);}if(cur.right!=null){queue.offer(cur.right);}}ret.add(temp);}return ret;}

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

    public 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;}}while (!queue.isEmpty()){TreeNode cur = queue.poll();if (cur != null){return false;}}return true;}

1.首先如果这棵树为null,那么是完全二叉树返回true。

11.寻找节点路径问题

    private boolean getPath(TreeNode root,TreeNode node,Stack<TreeNode> stack ){if(root == null || node == null){return false;}stack.push(root);if(root == node){return true;}boolean flg = getPath(root.left,node,stack);if(flg == true){return true;}boolean flg2 = getPath(root.right,node,stack);if(flg2 == true){return true;}stack.pop();return false;}

这个思想很简单。

1.如果树为null或节点为null那么没有找到路径,返回false。
2.接着将根节点添加到栈中。如果根节点为要找的节点。那么返回true。
3.接着去树的左边找,右边找。将每次路过的节点都添加到栈中。
4.如果左右两边都没有要找的节点。那么就弹出这个“根节点”。
5.最终栈留下来的就是我们要找的节点的路径了。返回true。

《Java数据结构》—二叉树的基本操作代码的具体实现

四、面试题练习

  1. 检查两颗树是否相同
/*** 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 boolean isSameTree(TreeNode p, TreeNode q) {if(p == null && q == null){return true;}if(p != null && q == null || p == null && q != null){return false;}if(p.val != q.val){return false;}return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);}
}
  1. 另一棵树的字树
/*** 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 boolean isSubtree(TreeNode root, TreeNode subRoot) {if(root == null){return false;//容易漏掉}if(isSameTree(root,subRoot)){return true;}if(isSubtree(root.left,subRoot)){return true;}if(isSubtree(root.right,subRoot)){return true;}return false; }public boolean isSameTree(TreeNode p, TreeNode q) {if(p == null && q == null){return true;}if(p != null && q == null || p == null && q != null){return false;}if(p.val != q.val){return false;}return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);}
}
  1. 翻转二叉树
/*** 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 TreeNode invertTree(TreeNode root) {if(root == null){return null;}TreeNode temp = root.left;root.left = root.right;root.right = temp;invertTree(root.left);invertTree(root.right);return root;}
}
  1. 平衡二叉树
class Solution {public boolean isBalanced(TreeNode root) {if(root == null){return true;}return biTreeHight(root)>=0;}public int biTreeHight(TreeNode root){if(root == null){return 0;}int hl = biTreeHight(root.left);int hr = biTreeHight(root.right);if(Math.abs(hl-hr)<=1&&hl>=0&&hr>=0){return Math.max(hl,hr)+1;}else{return -1;}}
}
  1. 对称二叉树

class Solution {public boolean isSymmetric(TreeNode root) {if(root == null){return true;}return isSymmetricChild(root.left,root.right);   }public boolean isSymmetricChild(TreeNode p,TreeNode q){if(p == null && q == null){return true;}if(p != null && q == null ||p == null && q != null){return false;}if(p.val != q.val){return false;}return isSymmetricChild(p.left,q.right)&& isSymmetricChild(p.right,q.left);}
}
  1. 二叉树的构建及遍历
import java.util.Scanner;class TreeNode{char val;TreeNode left;TreeNode right;public TreeNode(char val){this.val = val;}
}
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseString str = in.nextLine();TreeNode root = createTree(str);inOrder(root);}}public static int i = 0;public static TreeNode createTree(String str){TreeNode root = null;if(str.charAt(i) != '#'){root = new TreeNode(str.charAt(i));i++;root.left = createTree(str);root.right = createTree(str);}else{i++;}return root;}public static void inOrder(TreeNode root){if(root == null){return;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}
}
  1. 二叉树的层序遍历
class Solution {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> temp = new ArrayList<>();while ((size!=0)){TreeNode cur = queue.poll();temp.add(cur.val);size--;if(cur.left!=null){queue.offer(cur.left);}if(cur.right!=null){queue.offer(cur.right);}}ret.add(temp);}return ret;}
}
  1. 二叉树的最近公共祖先
class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root == null){return null;}Stack<TreeNode> stackP = new Stack<>();Stack<TreeNode> stackQ = new Stack<>();getPath(root,p,stackP);getPath(root,q,stackQ);int sizeP = stackP.size();int sizeQ = stackQ.size();if(sizeP>sizeQ){int size = sizeP-sizeQ;while(size != 0){stackP.pop();size--;}}else{int size = sizeQ-sizeP;while(size != 0){stackQ.pop();size--;}           }while(!stackP.isEmpty() && !stackQ.isEmpty()){if(stackP.peek().equals(stackQ.peek())){return stackP.peek();}stackP.pop();stackQ.pop();}return null;}private boolean getPath(TreeNode root,TreeNode node,Stack<TreeNode> stack ){if(root == null || node == null){return false;}stack.push(root);if(root == node){return true;}boolean flg = getPath(root.left,node,stack);if(flg == true){return true;}boolean flg2 = getPath(root.right,node,stack);if(flg2 == true){return true;}stack.pop();return false;}
}
//利用递归
class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root == null){return null;}if(p == root || q == root){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;}}
}
  1. 根据一棵树的前序与中序遍历序列构造二叉树
class Solution {public int preIndex;//成员变量public TreeNode buildTree(int[] preorder, int[] inorder) {return buildTreeChild(preorder,inorder,0,inorder.length-1);}private TreeNode buildTreeChild(int[] preorder,int[] inorder,int inbegin,int inend){//1.若没有左树或者没有右树if(inbegin>inend){return null;}//2.创建根节点TreeNode root = new TreeNode(preorder[preIndex]); //3.从中序遍历中找到根节点下标int rootIndex = findIndex(inorder,inbegin,inend,preorder[preIndex]);if(rootIndex == -1){return null;}preIndex++;//4.先创建左子树 后创建右子树root.left = buildTreeChild(preorder,inorder,inbegin,rootIndex-1);root.right = buildTreeChild(preorder,inorder,rootIndex+1,inend);return root;}private int findIndex(int[] inorder,int inbegin,int inend,int key){for(int i = inbegin; i<= inend ; i++){if(inorder[i] == key){return i;}}return -1;}
}
  1. 根据一棵树的中序与后序遍历序列构造二叉树
/*** 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 int postIndex;//成员变量public TreeNode buildTree(int[] inorder,int[] postorder) {postIndex = postorder.length-1;return buildTreeChild(postorder,inorder,0,inorder.length-1);}private TreeNode buildTreeChild(int[] postorder,int[] inorder,int inbegin,int inend){//1.若没有左树或者没有右树if(inbegin>inend){return null;}//2.创建根节点TreeNode root = new TreeNode(postorder[postIndex]); //3.从中序遍历中找到根节点下标int rootIndex = findIndex(inorder,inbegin,inend,postorder[postIndex]);if(rootIndex == -1){return null;}postIndex--;//4.先创建左子树 后创建右子树root.right = buildTreeChild(postorder,inorder,rootIndex+1,inend);root.left = buildTreeChild(postorder,inorder,inbegin,rootIndex-1);return root;}private int findIndex(int[] inorder,int inbegin,int inend,int key){for(int i = inbegin; i<= inend ; i++){if(inorder[i] == key){return i;}}return -1;}
}
  1. 根据二叉树创建字符串
class Solution {public String tree2str(TreeNode root) {if (root == null) {return "";}if (root.left == null && root.right == null) {return Integer.toString(root.val);}if (root.right == null) {return new StringBuffer().append(root.val).append("(").append(tree2str(root.left)).append(")").toString();}return new StringBuffer().append(root.val).append("(").append(tree2str(root.left)).append(")(").append(tree2str(root.right)).append(")").toString();}
}
  1. 二叉树的前序遍历(非递归实现)
/*** 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) {List<Integer> ret = new ArrayList<>();if(root == null){return ret;}ret.add(root.val);List<Integer> leftTree = preorderTraversal(root.left);ret.addAll(leftTree);List<Integer> rightTree = preorderTraversal(root.right);ret.addAll(rightTree);return ret;}
}
  1. 二叉树的中序遍历(非递归实现)
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> ret = new ArrayList<>();if(root == null){return ret;}List<Integer> leftTree = inorderTraversal(root.left);ret.addAll(leftTree);ret.add(root.val);List<Integer> rightTree = inorderTraversal(root.right);ret.addAll(rightTree);return ret;}
}
  1. 二叉树的后序遍历(非递归实现)
/*** 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) {List<Integer> ret = new ArrayList<>();if(root == null){return ret;}List<Integer> leftTree = postorderTraversal(root.left);ret.addAll(leftTree);List<Integer> rightTree = postorderTraversal(root.right);ret.addAll(rightTree);ret.add(root.val);return ret;}
}

相关文章:

《Java初阶数据结构》----5.<二叉树的概念及使用>

前言 大家好&#xff0c;我目前在学习java。之前也学了一段时间&#xff0c;但是没有发布博客。时间过的真的很快。我会利用好这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…...

git查看记录详解

文章目录 git查看记录查看文件修改列表查看修改差异友好的查看修改记录结合多个选项查看记录示例输出 git查看记录 使用 git log 你不仅可以查看提交记录&#xff0c;还可以通过一些选项查看文件的修改列表、修改差异&#xff0c;并以更友好的方式查看修改记录。以下是一些常用…...

检索增强生成RAG系列10--RAG的实际案例

讲了很多理论&#xff0c;最后来一篇实践作为结尾。本次案例根据阿里云的博金大模型挑战赛的题目以及数据集做一次实践。 完整代码地址&#xff1a;https://github.com/forever1986/finrag.git 本次实践代码有参考&#xff1a;https://github.com/Tongyi-EconML/FinQwen/ 目录 …...

程序员自我提升的全面指南

程序员自我提升的全面指南 1. 技术基础巩固重要性实践方法 2. 技术栈拓展重要性实践方法 3. 软技能提升重要性实践方法 4. 实践与项目经验重要性实践方法 5. 持续学习与职业规划重要性实践方法 6. 代码质量与优化重要性实践方法 7. 思维与创新能力重要性实践方法 8. 健康与心理…...

【golang】Golang手写元组 tuple | golang tuple

Golang手写元组 tuple 1、源码 如下&#xff1a; package tupletype Tuple[T any, U any] struct {First TSecond U }// zip combines elements of two slices into a slice of pairs (tuples), which is useful for combining related data. func Zip[T any, U any](slice…...

golang中struct的tag -简记

今天 简单整理一下&#xff0c;关于golang中struct的tag type User struct {UId int gorm:"column:uid;type:bigint;unique_index;not null;comment:用户id"Name string json:"name"Age int bson:"age"From string binding:"requi…...

分布式领域扩展点设计稿

分布式领域扩展点设计稿 背景坐标设计理念设计图Quick Start相关组件 背景 随着交易业务和基础知识的沉淀&#xff0c;愈发觉得扩展点可以在大型交易分布式架构中可以做更多的事情。 经过一个月的思考&#xff0c;决定将 单点领域扩展点&#xff08;savior-ext&#xff09; 从…...

玩转微信公众号变现:从新手到专家的全攻略

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…...

JVM: 方法调用

文章目录 一、介绍二、方法调用的原理1、静态绑定2、动态绑定&#xff08;1&#xff09;介绍&#xff08;2&#xff09;原理 一、介绍 在JVM中&#xff0c;一共有五个字节码指令可以执行方法调用&#xff1a; invokestatic: 调用静态方法。invokespecial&#xff1a;调用对象…...

测试面试宝典(四十一)—— 接口自动化的优缺点

接口自动化测试的优点&#xff1a; 1. 提高测试效率&#xff1a;能够快速执行大量的测试用例&#xff0c;节省了手动测试重复执行的时间和人力成本。 2. 尽早发现问题&#xff1a;可以在软件开发的早期阶段介入&#xff0c;有助于及时发现接口层面的缺陷&#xff0c;降低修复…...

“火炬科企对接”先进计算产业推进会 | 麒麟信安受邀参加,并签署开源生态合作协议

7月30日&#xff0c;“火炬科企对接”先进计算产业推进会在长沙隆重召开。大会由工业和信息化部火炬高技术产业开发中心、湖南省科学技术厅、湖南省工业和信息化厅、湖南湘江新区管理委员会、中国邮政储蓄银行联合举办。麒麟信安与来自国内先进计算领域的专家学者&#xff0c;2…...

中文网址导航模版HaoWa1.3.1/模版网站wordpress导航主题

HaoWa v1.3.1由挖主题开发的一款网址导航类主题。 HaoWA主题除主体导航列表外&#xff0c;对主题所需的小模块都进行了开放式的HTML编辑器形式的功能配置&#xff0c;同时预留出默认的代码结构&#xff0c;方便大家在现有的代码结构上进行功能调整。 同时加入了字体图标Font …...

图欧学习资源网创站以来的更新日志(截止至2022.5.6)不完全统计

一、网站创立和初步发展 2021年10月28日创建【TUO图欧视频备份站】&#xff0c;当时只有【单词视频】文件夹. 小学、初中、高中、大学、四六级、专四、专八、专升本、考研、考博、托福、雅思、托业、GRE、SAT、GMAT、MBA、新概念等 数量&#xff1a;500个文件&#xff0c;60个…...

现代前端架构介绍(第二部分):如何将功能架构分为三层

远离JavaScript疲劳和框架大战&#xff0c;了解真正重要的东西 在这个系列的前一部分 《App是如何由不同的构建块构成的》中&#xff0c;我们揭示了现代Web应用是由不同的构建块组成的&#xff0c;每个构建块都承担着特定的角色&#xff0c;如核心、功能等。在这篇文章中&#…...

LeetCode Easy|【21. 合并两个有序链表】

力扣题目链接 状态&#xff1a;拿到本题的第一反应就是使用双指针&#xff0c;分别指向两个链表的开头位置。 随后的思路就是以第一条链表为基准完成插入&#xff0c;并且对于遍历到的每个节点都应该保存其状态。 写了一下代码后发现&#xff0c;我们应该以第一个节点较小的链表…...

大模型的架构参数是指定义模型基本结构和组成的各种参数,这些参数对模型的性能、训练效率和泛化能力具有重要影响。以下是对大模型架构参数的详细介绍

大模型架构参数 大模型的架构参数是指定义模型基本结构和组成的各种参数&#xff0c;这些参数对模型的性能、训练效率和泛化能力具有重要影响。以下是对大模型架构参数的详细介绍&#xff1a; 一、基本结构和组成 层数&#xff1a;模型的层数是指模型中全连接网络或特定结构…...

人工智能会越来越闭源——对话东北大学副教授王言治 | Open AGI Forum

作者 | Annie Xu 责编、采访 | Echo Tang 出品丨GOSIM 开源创新汇 在读期间研究方向为并不“火”的模式识别与深度学习&#xff0c;毕业却刚好踩上人工智能计算研究的风口……来自美国东北大学的王言治副教授深耕深度学习与大模型&#xff0c;前瞻性地探索大模型的本地化部署…...

【前端】(仅思路)如何在前端实现一个fc手柄,将手机作为游戏手柄设备。

文章目录 背景界面demo原型图&#xff08;没错&#xff0c;就是它&#xff0c;童年回忆&#xff09; 遇到的问题最终后端demo(甚至比前端逻辑更简单) 背景 突发奇想&#xff0c;想要在前端实现一个fc游戏手柄&#xff0c;然后控制电脑的nes模拟器玩玩魂斗罗。 思路很简单&…...

三十种未授权访问漏洞合集

未授权访问漏洞介绍 未授权访问可以理解为需要安全配置或权限认证的地址、授权页面存在缺陷&#xff0c;导致其他用户可以直接访问&#xff0c;从而引发重要权限可被操作、数据库、网站目录等敏感信息泄露。---->目录遍历 目前主要存在未授权访问漏洞的有:NFS服务&a…...

【Golang 面试 - 进阶题】每日 3 题(十五)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

2025-05-08-deepseek本地化部署

title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek&#xff1a;小白也能轻松搞定&#xff01; 如何给本地部署的 DeepSeek 投喂数据&#xff0c;让他更懂你 [实验目的]&#xff1a;理解系统架构与原…...