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

【数据结构】树与二叉树

目录

1、树的概念及结构

1.1、概念

1、树的特点

2、树与非树

1.2、概念 (重要)

1.3、树的表示形式

2、二叉树(重点)

2.1、概念

2.2、二叉树的特点

2.3、两种特殊的二叉树

1、满二叉树

2、完全二叉树 

2.4、二叉树的性质        

​编辑✨ 练习

2.5、二叉树的存储

2.6、二叉树的遍历

2.6.1、前序遍历(先序遍历) 

2.6.2、中序遍历

2.6.3、后序遍历 

2.6.4、层序遍历

2.6.5、二叉树遍历练习 

2.7、二叉树的基本操作

2.7.1、获取树中结点的个数

2.7.2、获取叶子节点的个数

2.7.3、获取第k层结点的个数

2.7.4、获取二叉树的高度


1、树的概念及结构

1.1、概念

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

1、树的特点

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

2、树与非树


1.2、概念 (重要)

  •  结点的度:一个节点含有子树的个数称为该节点的度,也可以理解为节点含有的子节点的个数;如上图:A的度为6。
  • 树的度:树内各节点的度的最大值;如上图:树的度为6
  • 叶子节点或终端节点:度为0的节点常委叶子节点;如图:B、C、H、I、N、P、Q为叶子节点
  • 双亲节点和父节点:若一个节点含有子节点,则这个结点称为其子节点的父节点;如上图:A是B的父节点。
  • 孩子结点或子节点:一个结点含有的子树的根节点称为该节点的子节点;如上图:B是A的孩子结点
  • 根节点:一棵树中,没有双亲结点的结点;如上图:A
  • 结点的层次:从根节点定义起,根为第1层,跟的子节点为第2层,以此类推。
  • 树的高度或深度:树中结点的最大层次;如上图:树的高度为4

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

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

1.3、树的表示形式

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多种表示方式,如:双亲表示法、孩子表示法、孩子双亲表示法、孩子兄弟表示法等等。这里我们就简单的了解其中最常用的孩子兄弟表示法

class Node {int value; // 树中存储的数据Node firstChild; // 第一个孩子引用Node nextBrother; // 下一个兄弟引用
}


 


2、二叉树(重点)

2.1、概念

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

  1. 或者为空;
  2. 或者是由一个根结点加上两颗分别称为左子树和右子树的二叉树组成。


2.2、二叉树的特点

  • 每个结点最多有两棵子树,所以二叉树中不存在度大于2的结点。注意不是只有两棵子树,而是最多有。该节点没有子树或者有一颗子树都是可以的。
  • 左子树和右子树是有顺序的,次序不能任意颠倒,因此二叉树是有序树。
  • 即使树中某个节点只有一棵子树,也要区分它是左子树还是右子树


2.3、两种特殊的二叉树

1、满二叉树

定义(两种方式)

  1. 在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
  2. 一棵二叉树,如果每层的结点数都达到最大值,则这颗二叉树就是满二叉树

 单是每个结点都存在左右子树,不能算是满二叉树,还必须要所有的叶子都在通一层上,这就做到了整棵树的平衡。

满二叉树的特点 

  1. 叶子只能出现在最下一层。出现在其他层就不可能达成平衡。
  2. 非叶子结点的度一定是2.否则就是"去胳膊少腿"了。
  3. 在同一深度的二叉树中,满二叉树的结点个数最多,叶子树最多。
  4. 如果一棵满二叉树的层数为k,则它的结点总数是2^{k}-1.

2、完全二叉树 

✨定义:

对一棵具有n个结点的二叉树按层序编号,如果编号为i(1<i<n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这颗二叉树称为完全二叉树。

❗❗❗可以这样理解:

完全二叉树的所有结点与同样深度的满二叉树,他们按层序编号。两个二叉树中的节点编号是一一对应的。满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。

画图理解

✨ 完全二叉树的特点

  • 叶子结点只能出现在最下两层
  • 最下层的叶子一定集中在最左部连续位置
  • 倒数第二层,若有叶子节点,一定是在右部连续位置
  • 如果结点的度为1,则该结点只有左孩子,即不存在只有右子树的情况
  • 同样节点数的二叉树,完全二叉树的深度最小


2.4、二叉树的性质        

1、若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2^{i-1}(i > 0)个结点

 2、若规定只有根节点的二叉树的深度为1,则深度为K的二叉树的最大节点数是2^{k}-1(k >= 0)

3、对任何一棵二叉树,如果其叶子结点个数为n0度为2的非叶子结点个数为n2则有n0 = n2+1

论证:

通过学习树的知识,我们知道一棵N个结点的树有N-1条边 。

这条性质的意思是,任何一个二叉树中,度为0的结点比度为2的结点多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,有孩子序号,否则无右孩子

✨ 练习

1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为(B

A 、不存在这样的二叉树       B、200           C、198           D、199

 ❗题解:叶子结点也就是度为0的结点,已知度为2的结点为199个,根据公式n0 = n2 + 1;得度为0的结点为200个。

2、在具有 2n 个结点的完全二叉树中,叶子结点个数为(A

A n                      B n+1                       C n-1                       D n/2

❗题解: 

 3.一个具有767个节点的完全二叉树,其叶子节点个数为(B

A 383                                  B 384                              C 385                              D 386

❗题解:由于结点的个数为奇数,所以根据公式n = n0+n1+n2——》767 = n0+n2得公式1

再由度为0的节点数等于度为2的节点数+1:n0 = n2+1 得公式2

联立公式1和2得:767 = n0+n0-1  ——》768 = 2n0  ——》n0 = 384

故:叶子节点个数为384,所以选B

4.一棵完全二叉树的节点数为531个,那么这棵树的高度为( B

A 11                  B 10                          C 8                         D 12 

题解: n个结点的完全二叉树的深度为k = log_{2}(n+1)(向上取整)

所以k = log_{2}532,2^9 = 512,说明9层放不下所有结点,向上取整

所以这棵树的高度为10


2.5、二叉树的存储

二叉树的存储结构分为:顺序存储和类似于链表的链式存储。

二叉树的链式存储是通过一个一个的结点引用起来的,常见的表示方式由二叉和三叉表示方式。

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

 本章博客主要了解孩子表示法


2.6、二叉树的遍历

在学习二叉树的遍历以及后续的二叉树的基本操作的时候,首先要生成一个二叉树,但是生成一个二叉树需要用到递归,有些难度,这里我们手动创建一个二叉树,方便二叉树的遍历和基本操作方法的学习。

public class TestbinaryTree {//定义二叉树的类static class TreeNode{//定义结点public char val;public TreeNode left;//孩子结点,所以用TreeNode类型的引用public TreeNode right;public TreeNode(char val){this.val = val;}}public TreeNode root;//每个二叉树都有一个根节点public TreeNode createTree(){//通过调用这个方法来创建一个二叉树,不用担心在这个方
//法中创建了二叉树是局部变量,出了这个方法之后,创建的二叉树被回收,因为每个结点都被引用了TreeNode A = new TreeNode('A');TreeNode B = new TreeNode('B');TreeNode C = new TreeNode('C');TreeNode D = new TreeNode('D');TreeNode E = new TreeNode('E');TreeNode F = new TreeNode('F');TreeNode G = new TreeNode('G');TreeNode H = new TreeNode('H');A.left = B;A.right = C;B.left = D;B.right = E;C.left = F;C.right = G;E.right = H;this.root = A;return root;}}

学习二叉树最简单的方式就是遍历。所谓遍历是指沿着某条搜索路线,依次对树中每个结点均作一次且仅作一次访问。访问结点所作的操作依赖于具体的引用问题 (比如:打印结点内容、节点内容加1).遍历时二叉树上最重要的操作之一,时二叉树上进行其他运算的基础。


2.6.1、前序遍历(先序遍历) 

前序遍历  :访问根节点——》根的左子树——》根的右子树。

✨遍历流程:

  • 先遍历二叉树的根节点,若根节点A不为空,打印根节点A。
  • 再遍历根节点的左子树B,若左子树的根节点B不为空,打印B。
  • 再遍历B结点的左子树D,若左子树的根节点D不为空,打印D;为空,打印D,返回到D结点的根节点B。
  • 遍历B结点的右子树,输出根节点的值。
  • 依次为例,将整棵树遍历完成,每个结点只输出一次 。
  • 每次输出的都是树的根节点。

✨代码示例 :这里有两种思路:遍历思路子问题思路

写法一:遍历的思路(好理解)

 //前序遍历:根——》左子树——》右子树public void preOrder(TreeNode root){if(root == null){//递归的开始也是结束条件return ;//若根节点为空,则直接返回}System.out.println(root.val+" ");//若根不为空,先输出跟结点preOrder(root.left);//通过调用自己,实现递归,遍历左子树preOrder(root.right);}

✨递归过程 :

写法二 :子问题思路(难理解)

1.这个代码还是存在很多问题的,给了返回值类型,但是并没有将该方法的返回值用起来

    List<Integer> ret = new ArrayList<>();//用来记录遍历的结点的值public List<Integer> preorderTraversal(TreeNode root){if(root == null){return ret;//根节点为空,返回ret;}ret.add(root.val);//将根节点的值,放到ret当中preorderTraversal(root.left);//遍历左子树preorderTraversal(root.right);//遍历右子树return ret;}

2、这个是子问题思路比较合理的写法。

 public List<Integer> preorderTraversal(TreeNode root) {List<Integer> ret = new ArrayList<>();//每次调用这个方法,都会产生新的空间,用来记录这个方法遍历的内容if (root == null) {return ret;//根节点为空,返回ret;}ret.add(root.val);//将二叉树的根节点的值,放到ret当中//将左子树遍历到的内容放到左子树的数组中List<Integer> leftTree = preorderTraversal(root.left);//遍历左子树,并用List<Integer>类型的引用来接收方法的返回值ret.addAll(leftTree);//addAll方法用来向ret集合中添加一个集合对象所包含的所有内容//将右子树遍历到的内容放到右子树的数组中List<Integer> rightTree = preorderTraversal(root.right);//遍历右子树ret.addAll(rightTree);return ret;}


2.6.2、中序遍历

中序遍历:根的左子树——》根节点——》根的右子树

✨遍历流程 

  • 先遍历二叉树的左子树,若根节点A不为空,遍历A的左子树B.
  • 若B不为空,遍历他的左子树D,若D的左子树为空,则返回输出D,
  • 再遍历右子树,若右子树为空,则B的左子树遍历完成,返回到B,并输出B。
  • 再遍历B的右子树,若为空,则A的左子树遍历完成,返回输出A,
  • 再遍历A的右子树,
  • 以此为例,知道整棵树遍历完成。

✨代码示例 :

1、遍历的思路

    //中序遍历:左子树——》根节点——》右子树public void inOrder(TreeNode root){if(root == null){//递归的开始和结束条件return;//若根节点为空,则返回}inOrder(root.left);//若根节点不为空,则递归左子树System.out.println(root.val+" ");//左子树递归完成,打印根节点inOrder(root.right);//再递归右子树}

中序遍历的代码递归过程,就不再演示了,思路前序遍历相似。

2、子问题思路

  public List<Character> inOrder(TreeNode root) {List<Character> ret = new ArrayList<>();//每次调用这个方法,都会产生新的空间。if (root == null) {return ret;//根节点为空,返回ret;}//将左子树遍历到的结点的内容放到左子树的数组中List<Character> leftTree = inOrder(root.left);//遍历左子树,并用List<Integer>类型的引用来接收方法的返回值ret.addAll(leftTree);//addAll方法用来向ret集合中添加一个集合对象所包含的所有内容ret.add(root.val);//将二叉树的第一个根节点的值,放到ret当中//将右子树遍历到的结点的内容放到左子树的数组中List<Character> rightTree = inOrder(root.right);//遍历右子树ret.addAll(rightTree);return ret;}

2.6.3、后序遍历 

后序遍历:根的左子树——》根的右子树——》根节点

✨遍历流程

  • 先遍历二叉树的左子树,若跟结点A不为空,则遍历A的左子树B。
  • 若B不为空,则遍历B的左子树D。
  • 若D不为空,则遍历D的左子树,若D的左子树为空,则返回到D,再遍历D的右子树。
  • 若D的右子树为空,则返回输出根节点D,则B的左子树就遍历完成,返回到B,再遍历B的右子树。
  • 若B的右子树为空,则返回B,并输出A的左子树B,再返回A,再遍历A的右子树C。
  • 以此为例。直到遍历完整棵树。

✨代码示例 

1、遍历思路

    //后序遍历:左子树——》右子树——》根节点public void postOrder(TreeNode root){if(root == null){//递归的开始和结束条件return;//若根节点为空,则返回}postOrder(root.left);//若根节点不为空,则递归左子树postOrder(root.right);//再递归右子树System.out.println(root.val+" ");//左右子树都递归完成,打印根节点}

 2、子问题思路

  public List<Character> postOrder(TreeNode root) {List<Character> ret = new ArrayList<>();//每次调用这个方法,都会产生新的空间。if (root == null) {return ret;//根节点为空,返回ret;}//将左子树遍历到的结点的内容放到左子树的数组中List<Character> leftTree = postOrder(root.left);//遍历左子树,并用List<Integer>类型的引用来接收方法的返回值ret.addAll(leftTree);//addAll方法用来向ret集合中添加一个集合对象所包含的所有内容//将右子树遍历到的结点的内容放到左子树的数组中List<Character> rightTree = postOrder(root.right);//遍历右子树ret.addAll(rightTree);ret.add(root.val);//将二叉树的第一个根节点的值,放到ret当中return ret;}

✨遍历测试

以createTree中手动生成的树为例:前序遍历:ABDEHCFG;中序遍历:DBEHAFCG;后序遍历:DHEBFGCA。与测试结果相同。 

public class Test {public static void main(String[] args) {TestbinaryTree testbinaryTree = new TestbinaryTree();TestbinaryTree.TreeNode  root = testbinaryTree.createTree();System.out.println("==前序遍历==");testbinaryTree.preOrder(root);System.out.println();System.out.println("==中序遍历==");testbinaryTree.inOrder(root);System.out.println();System.out.println("==后序遍历==");testbinaryTree.postOrder(root);System.out.println();}}


2.6.4、层序遍历

设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根结点,然后从左到右访问第二层上的结点,接着是第三层的结点,以此类推,自上而下,自左至右逐层访问数的结点的过程就是层序遍历。


2.6.5、二叉树遍历练习 

1.某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。该完全二叉树的前序序列为(A)

A: ABDHECFG             B: ABCDEFGH               C: HDBEAFCG             D: HDEBFGCA

【题解】 

 

 2.二叉树的先序遍历和中序遍历如下:先序遍历:EFHIGJK;中序遍历:HFIEJKG.则二叉树根结点为(A)

A: E               B: F                    C: G                 D: H

 【题解】

 3.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为(D)

A: adbce           B: decab              C: debac               D: abcde

 【题解】

 4.某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同一层从左到右)的序列为(A)

A: FEDCBA                     B: CBAFED                    C: DEFCBA                     D: ABCDEF

【题解】 

 

❗❗❗ 总结:

  • 当前序遍历序列和中序遍历序列同时知道,可以得到后续遍历序列。
  • 当中序遍历序列和后序遍历序列同时知道,可以得到前序遍历序列。
  • 但是当后序遍历序列和前序遍历序列同时知道,不能得到中序遍历序列。
  • 前序遍历序列和后序遍历序列可以知道二叉树的根节点,中序遍历序列可以知道根节点的左右子树。

2.7、二叉树的基本操作

2.7.1、获取树中结点的个数

这个方法的递归公式可以用子问题思路来思考。

左子树结点个数+右子树结点个数+根节点 = 总节点数

当有左子树和右子树则用上述的公式,若没有则可以直接输出根节点1.

【代码示例】 

1、子问题思路:

    public int size(TreeNode root){if(root == null){return 1;}int leftSize = size(root.left);//这里的递归,每次走左边结点,查看子树的左右结点,然后将子树的左右结点加根节点的值返回。int rightSize = size(root.right);return leftSize + rightSize + 1;}

2、遍历思路

每个结点都是一个子树的根节点,当根节点不为空时,则+1

    public int nodeSize;public void size1(TreeNode root){if(root == null){return ;}nodeSize++;size1(root.left);size1(root.right);}

❗❗❗这个方法存在一个问题,当有两个二叉树都要求结点个数时,引用第一次结果是正确的,但是第二次就会出错,因为nodeSize 属性是属于某个引用的,在test类当中用同一个引用调用两次这个方法,那么第二次nodeSize的结果是将两个树中的结点都加在了一起。

❗❗❗总结:这个方法的时间复杂度为:O(N)

空间复杂度为O(logN) ,原因在于二叉树的遍历是先遍历左子树再遍历右子树,所以再极端情况下,他能开辟的空间就是树的高度。


2.7.2、获取叶子节点的个数

❗❗❗思路:

  • 当一个二叉树的结点的左右子树都为空,则这个结点就是二叉树的叶子结点。
  • 所以当根节点为空时,二叉树为空,返回0,
  • 当根节点不为空时,且二叉树中某个结点的左右子树都为空时,则这个结点为叶子节点,返回1

✨代码示例 

1、子问题思路

   public int getLeafNodeCount(TreeNode root){if(root == null){return 0;}if(root.right == null&&root.left == null){//这里判断是叶子节点,记录一个结点1.return 1;}//这两个if条件作为递归的结束条件int leftSize = getLeafNodeCount(root.left);int rightSize = getLeafNodeCount(root.right);return leftSize+rightSize;//将左右两个子树的叶子结点加起来}

2、遍历思路

    public int leafSize;public void getLeafNodeCount2(TreeNode root){if(root == null){return;}if(root.left == null&&root.right == null){leafSize++;//遍历一个叶子节点+1}getLeafNodeCount2(root.left);//调用该方法遍历左子树。getLeafNodeCount2(root.right);}


2.7.3、获取第k层结点的个数

以下面的二叉树为例,第k = 3层的结点的个数

 ✨子问题思路:

当要求A树的第3层结点个数时,则要求A树的左子树B的k-1层结点个数和A树的右子数C的k-1层结点个数的合。

✨代码示例

    //获取第k层结点的个数public int getLevelNodeCount(TreeNode root,int k){if(root == null){return 0;}if(k == 1){return 1;}int leftSize = getLevelNodeCount(root.left,k-1);int rightSize = getLevelNodeCount(root.right,k-1);return leftSize+rightSize;}


2.7.4、获取二叉树的高度

以下列的二叉树为例

✨子问题思路 

  • 每次遍历的都是树的根节点,当根节点为空时,递归结束。
  • 那么左子树的高度也就确定。
  • 以同样的方式遍历右子树,确定右子树的高度
  • 再将两个树的高度进行比较,最大的高度+1就是该二叉树的高度。

✨代码示例 

    //获取二叉树的高度public int getHeight(TreeNode root){if(root == null){return 0;}int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);return (leftHeight>rightHeight)?(leftHeight+1):(rightHeight+1);}

相关文章:

【数据结构】树与二叉树

目录 1、树的概念及结构 1.1、概念 1、树的特点 2、树与非树 1.2、概念 &#xff08;重要&#xff09; 1.3、树的表示形式 2、二叉树&#xff08;重点&#xff09; 2.1、概念 2.2、二叉树的特点 2.3、两种特殊的二叉树 1、满二叉树 2、完全二叉树 2.4、二叉树的性…...

Stress压力工具的部署及使用

Stress压力工具的部署及使用 下载地址&#xff1a;wget https://fossies.org/linux/privat/old/stress-1.0.5.tar.gz 1.部署 进入目录执行./autogen.sh [rootiZ2ze1pj93eyq389c2ppi5Z stress-1.0.5]# ./autogen.sh ps&#xff1a;如果执行过程中缺包&#xff0c;安装对应的…...

[蓝桥杯 2020 省 AB3] 乘法表

题目描述九九乘法表是学习乘法时必须要掌握的。在不同进制数下&#xff0c;需要不同的乘法表。例如, 四进制下的乘法表如下所示&#xff1a;1*11 2*12 2*210 3*13 3*212 3*321请注意&#xff0c;乘法表中两个数相乘的顺序必须为样例中所示的顺序&#xff0c;不能随意交换两个乘…...

Python基础知识

基础知识 基础知识包括输入输出、变量、数据类型、表达式、运算符这5个方面。 1.输入输出 Python有很多函数&#xff0c;后面我们会细讲&#xff0c;但这里先将两个最基本的函数&#xff1a;输入和输出。 输出函数print()&#xff0c;在前面我们已经用过了&#xff0c;语法…...

FME案例实战教程:聚焦实战应用,摆脱思路束缚,您值得拥有

一、教程链接&#xff08;一&#xff09;FME案例实战教程链接1.FME案例实战教程&#xff08;完整版&#xff09; ☚强烈推荐☚2.FME案例实战教程&#xff08;A组&#xff09;3.FME案例实战教程&#xff08;B组&#xff09;4.FME案例实战教程&#xff08;C组&#xff09;&#…...

【JavaScript】根据元素内容遍历元素的方案

▒ 目录 ▒&#x1f6eb; 导读需求1️⃣ jQuery2️⃣ XPATH&#xff08;document.evaluate&#xff09;3️⃣ 原生js&#xff08;querySelectorAll & Array&#xff09;&#x1f6ec; 文章小结&#x1f4d6; 参考资料&#x1f6eb; 导读 需求 因业务需要&#xff0c;根据元…...

kafka全解

目录Kafka概述定义消息队列目录结构分析传统消息队列的应用场景消息队列的两种模式点对点模式发布/订阅模式Kafka基础架构Kafka快速入门安装部署集群规划集群部署集群启停脚本Kafka命令行操作Kafka基础架构主题命令行操作生产者命令行操作消费者命令行操作kafka可视化工具Kafka…...

(三)随处可见的LED广告屏是怎么工作的呢?接入GUI

续上文&#xff0c;本篇我们将尝试接入一个GUI来控制点阵屏。在前两篇中&#xff0c;我们相继介绍了点阵屏的控制原理&#xff0c;以及如何让点阵屏按照我们所想的进行显示。本篇将在此基础上接入一个GUI&#xff0c;使点阵屏的控制更加优雅。限于阅读体验和展示效果&#xff0…...

线程池简介

线程池 线程池&#xff08;英语&#xff1a;thread pool&#xff09;&#xff1a;一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时…...

大数据面试题集锦-Hadoop面试题(四)-YARN

你准备好面试了吗?这里有一些面试中可能会问到的问题以及相对应的答案。如果你需要更多的面试经验和面试题&#xff0c;关注一下"张飞的猪大数据分享"吧&#xff0c;公众号会不定时的分享相关的知识和资料。 文章目录1、为什么会产生 yarn,它解决了什么问题&#xf…...

Python---time模块

专栏&#xff1a;python 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;Python在学&#xff0c;希望能够得到各位的支持&#xff01;&#xff01;&#xff01; time模块前言时间戳time.time()将时间戳转换成字符串time.ctime()将时间戳转换为元组time.localtime(时间戳)将元…...

坚鹏:学习贯彻二十大精神 解码共同富裕之道(面向银行)

学习贯彻二十大精神 解码共同富裕之道课程背景&#xff1a; 很多银行从业人员存在以下问题&#xff1a;不知道如何准确解读二十大精神&#xff1f;不清楚共同富裕相关政策要求&#xff1f;不知道如何有效推动共同富裕&#xff1f; 课程特色&#xff1a;有实战案例有…...

python查看程序的cpu和内存资源占用情况

1.获取线程消耗的内存 :线程内存使用的概念没有明确定义。线程共享它们的内存。唯一真正的线程本地内存是它的调用堆栈&#xff0c;除非您认真地递归地做一些事情&#xff0c;否则这不是有趣的部分。 2.获取进程消耗的内存 3.获取程序消耗的内存 mprof run endpoint.py 4.查看…...

番外10:使用ADS对射频功率放大器进行非线性测试2(使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试)

番外10&#xff1a;使用ADS对射频功率放大器进行非线性测试2&#xff08;使用带宽20MHz的64QAM信号进行ACLR、EVM、CCDF测试&#xff09; 1、基本理论 功率放大器的非线性性能十分重要&#xff0c;特别是对于当前广泛使用的移动设备。由于其各种复杂的信号调制&#xff0c;功…...

Ubuntu搭建maven私服

1.安装JDK8 已经是JDK8的需要配置环境变量&#xff0c;如果是更高版本的JDK则需要修改nexus配置文件 2.下载nexus安装包 百度网盘下载&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1DfKqql8tZNQXEBxAEH7UyA 提取码&#xff1a;hx4p安装到有磁盘的目录如下所示&…...

【JavaWeb】Servlet基础

文章目录1.Tomcat服务器安装注意事项2.编写WebApp3.BS系统角色和协议4.模拟Servlet4.1模拟sun公司4.2模拟Tomcat服务器4.3模拟WebApp开发者5.开发一个带有Servlet的WebApp5.1创建一个名为crm的项目5.2 在项目中创建一个名为WEB-INF的文件&#xff08;必须&#xff09;5.3在WEB-…...

pinia + pinia-plugin-persistedstate + 组合式API 写法,持久化失效问题

持久化失效卡了一天的问题安装使用就不多说了&#xff0c;主要是针对持久化失效的几个问题说明和解决方法首先是组合式写法&#xff0c;配置持久化export const useUserStore defineStore(user, () > {},{persist: true} )defineStore 第三个参数&#xff0c;具体可以看 p…...

ptrace 调式详解

在程序出现bug的时候&#xff0c;最好的解决办法就是通过 GDB 调试程序&#xff0c;然后找到程序出现问题的地方。比如程序出现 段错误&#xff08;内存地址不合法&#xff09;时&#xff0c;就可以通过 GDB 找到程序哪里访问了不合法的内存地址而导致的。本文不是介绍GDB不是使…...

【AI绘画】绝美春天插画,人人都是插画师

春天&#xff0c;自然界重新苏醒&#xff0c;生机勃勃&#xff0c;百花争艳&#xff0c;万籁俱寂。一切都被新的生命活力所染上。春风拂面&#xff0c;一股清新的空气流过&#xff0c;仿佛带着一种神秘的力量&#xff0c;让人心旷神怡&#xff0c;心情舒畅、轻松愉悦。 突然&a…...

蓝桥杯入门即劝退(二十四)重复的子字符串(被秒杀)

欢迎关注点赞评论&#xff0c;共同学习&#xff0c;共同进步&#xff01; ------持续更新蓝桥杯入门系列算法实例-------- 如果你也喜欢Java和算法&#xff0c;欢迎订阅专栏共同学习交流&#xff01; 你的点赞、关注、评论、是我创作的动力&#xff01; -------希望我的文章…...

针对序列级和词元级应用微调BERT(需修改)

对于序列级和词元级自然语言处理应用&#xff0c;BERT只需要最小的架构改变&#xff08;额外的全连接层&#xff09;&#xff0c;如单个文本分类&#xff08;例如&#xff0c;情感分析和测试语言可接受性&#xff09;、文本对分类或回归&#xff08;例如&#xff0c;自然语言推…...

(四十七)大白话表锁和行锁互相之间的关系以及互斥规则是什么呢?

今天我们接着讲&#xff0c;MySQL里是如何加表锁的。这个MySQL的表锁&#xff0c;其实是极为鸡肋的一个东西&#xff0c;几乎一般很少会用到&#xff0c;表锁分为两种&#xff0c;一种就是表锁&#xff0c;一种是表级的意向锁&#xff0c;我们分别来看看。 首先说表锁&#xf…...

织梦TXT批量导入TAG标签并自动匹配相关文章插件

织梦TXT批量导入TAG标签并自动匹配相关文章插件是一种非常有用的插件&#xff0c;它可以帮助网站管理员快速地将TAG标签添加到文章中&#xff0c;并自动匹配相关文章。 以下是该织梦TXT批量导入TAG标签插件的几个优点&#xff1a; 1、提高网站的SEO效果&#xff1a;TAG标签是搜…...

Sentinel架构篇 - 10分钟带你看滑动窗口算法的应用

限流算法 以固定时间窗口算法和滑动时间窗口算法为例&#xff0c;展开两种限流算法的分析。 固定时间窗口算法 在固定的时间窗口内&#xff0c;设置允许固定数量的请求进入。如果超过设定的阈值就拒绝请求或者排队。 具体的&#xff0c;按照时间划分为若干个时间窗口&#…...

redis主从复制

<1> redis主从复制介绍&#xff1a; 首先来介绍一下什么是redis主从复制 Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。但如果当把数据存储在单个Redis的实例中&#xff0c;当读写体量比较大的时候&#xff0c;服务端就很难承受…...

近期常见组件漏洞更新:

&#xff08;1&#xff09;mysql 5.7 在2023年1月17日&#xff0c;发布了到5.7.41版本 mysql 8.0 在2023年1月17日&#xff0c;发布了到8.0.32版本 MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ &#xff08;2&#xff09;Tomcat8在202…...

深度学习常用的激活函数总结

各种激活函数总结 目录一、sigmoid二、tanh![在这里插入图片描述](https://img-blog.csdnimg.cn/a0d92552edf8464db793fdd2f2b75cb5.png)三、ReLU系列1.原始ReLU2.ReLU改进&#xff1a;Leaky ReLU四、swish五、GeLU一、sigmoid 优点&#xff1a; 1.可以将任意范围的输出映射到 …...

Java编程问题top100---基础语法系列(二)

Java编程问题top100---基础语法系列&#xff08;二&#xff09;六、如何测试一个数组是否包含指定的值&#xff1f;简单且优雅的方法:自己动手写逻辑对象数组JDK 8 APIJDK 9 API Set.of()七、重写&#xff08;Override&#xff09;equlas和hashCode方法时应考虑的问题理论上讲&…...

网页打印与导出word实现在A4纸上相同效果

在工作中遇到这样一个需求&#xff0c;客户要求&#xff1a; 1、实现在浏览器中打印和导出到word中&#xff0c;要求浏览器打印出来的效果和word中打印的效果基本一致。2、打印的内容要自动分页&#xff0c;第一页的顶部有文件头&#xff0c;最后一页的底部有页尾。 这里记录一…...

备战英语6级——记录复习进度

开始记录—— 学习&#xff1a;如何记录笔记&#xff1f; 1&#xff1a;首先我认为&#xff1a;电脑打字比较适合我&#xff01; 2&#xff1a;先记笔记&#xff0c;再“填笔记”&#xff01; 记笔记就是一个框架&#xff0c;记录一个大概的东西。后面需要在笔记中&#xff0…...

实例10:四足机器人运动学逆解可视化与实践

实例10&#xff1a; 四足机器人运动学逆解单腿可视化 实验目的 了解逆运动学的有无解、有无多解情况。了解运动学逆解的求解。熟悉逆运动学中求解的几何法和代数法。熟悉单腿舵机的简单校准。掌握可视化逆向运动学计算结果的方法。 实验要求 拼装一条mini pupper的腿部。运…...

Elasticsearch7.8.0版本优化——路由选择

目录一、Elasticsearch 如何知道一个文档存放在哪个分片二、不带 routing 查询三、带 routing 查询一、Elasticsearch 如何知道一个文档存放在哪个分片 其实是通过这个公式来计算出来&#xff1a;shard hash(routing) % number_of_primary_shardsrouting 默认值是文档的 id&a…...

Go常量的定义和使用const,const特性“隐式重复前一个表达式”,以及iota枚举常量的使用

Go常量的定义和使用const,以及iota枚举常量的使用Go常量constGo中常量的定义和使用Go特性const,"隐式重复前一个表达式"iota 实现枚举常量Go常量const Go语言中的const整合了C语言中的宏定义常量&#xff0c;const只读变量枚举变量 绝大多数情况下&#xff0c;Go常…...

Git学习(1)pro git阅读

目录 目录&#xff1a; 1. 起步 2. Git 基础 3. Git 分支 4. 服务器上的 Git 5. 分布式 Git 第一章 1.3 Git是什么 1.6运行git前的配置 该开源图书网站 Git - Book (git-scm.com) 目录&#xff1a; 1. 起步 1.1 关于版本控制1.2 Git 简史1.3 Git 是什么&#xff1f;1…...

PHY自协商

1. 自协商定义 自动协商模式是端口根据另一端设备的连接速度和双工模式&#xff0c;自动把它的速度调节到最高的公共水平&#xff0c;即线路两端能具有的最快速度和双工模式。 自协商功能允许一个网络设备能够将自己所支持的工作模式信息传达给网络上的对端&#xff0c;并接受对…...

【大数据离线开发】8.2 Hive的安装和配置

8.3 Hive的安装和配置 安装模式&#xff1a; 嵌入模式 &#xff1a;不需要使用MySQL&#xff0c;需要Hive自带的一个关系型数据库&#xff1a;Derby本地模式、远程模式 ----> 需要MySQL数据库的支持 安装 hive 安装包 1、解压tar -zxvf apache-hive-2.3.0-bin.tar.gz -C…...

Capture Modules:车载网络报文捕获模块

&#xff08;以下所有图片均来源于Technica官网&#xff09; Technica Engineering的新一代硬件设备&#xff0c;即Capture Modules&#xff0c;提供了五种变体以涵盖不同带宽的车载以太网&#xff08;100BASE-T1和1000BASE-T1&#xff09;以及常见的IVN技术&#xff08;CAN、C…...

数据结构与算法系列之时间与空间复杂度

这里写目录标题算法的复杂度大O的渐进表示法实例分析空间复杂度每日一题算法的复杂度 衡量一个算法的好坏&#xff0c;一般 是从时间和空间两个维度来衡量的&#xff0c; 即时间复杂度和空间复杂度。 时间复杂度主要衡量一个算法的运行快慢&#xff0c; 空间复杂度主要衡量一个…...

Python代码使用PyQt5制作界面并封装

目录参考链接续&#xff1a;https://blog.csdn.net/yulinxx/article/details/93344163 若要对此程序进行封装&#xff0c;加个界面&#xff0c;然后制作成 EXE&#xff0c; 使用 PyQt5 制作界面&#xff0c;PyInstaller 进行封装成 EXE 可参考&#xff1a; Python制作小软件…...

【Node.js】MySQL数据库的第三方模块(mysql)

mysql安装操作MySQL数据库的第三方模块&#xff08;mysql&#xff09;通过第三方模块&#xff08;mysql2&#xff09;连接到MySQL数据库mysql插入数据mysql插入数据的便捷方式mysql更新数据mysql更新数据的便捷方式mysql删除数据安装操作MySQL数据库的第三方模块&#xff08;my…...

Docker中安装并配置单机版redis

1、使用docker安装redis 搜索Reis镜像&#xff0c;这里展示的是官方最新的镜像docker search redis 使用官方dockerhub搜索redis 2、选用常用的redis5.0作为安装的版本docker pull redis:5.0 3、运行redis容器的两种方式 3.1 不映射外部配置文件直接运行redis5.0镜像docker …...

模拟微信聊天-课后程序(JAVA基础案例教程-黑马程序员编著-第八章-课后作业)

【案例9-1】 模拟微信聊天 【案例介绍】 1.案例描述 在如今&#xff0c;微信聊天已经人们生活中必不可少的重要组成部分&#xff0c;人们的交流很多都是通过微信来进行的。本案例要求&#xff1a;将多线程与UDP通信相关知识结合&#xff0c;模拟实现微信聊天小程序。通过监…...

html2canvas将页面dom元素内容渲染成图片保存至本地

html2canvas:https://html2canvas.hertzen.com/configuration/ github:https://github.com/niklasvh/html2canvas 效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compa…...

前端进阶JS运行原理

JS运行原理 深入了解V8引擎原理 浏览器内核是由两部分组成的&#xff0c;以webkit为例&#xff1a; WebCore&#xff1a;负责HTML解析、布局、渲染等等相关的工作&#xff1b;JavaScriptCore&#xff1a;解析、执行JavaScript代码&#xff1b; 官方对V8引擎的定义&#xff1…...

Python识别二维码的两种方法(cv2)

在学习Python处理二维码的过程中&#xff0c;我们看到的大多是“用python生成酷炫二维码”、“用Python制作动图二维码”之类的文章。而关于使用Python批量识别二维码的教程&#xff0c;并不多见。所以今天我会给大家分享两种批量识别二维码的Python技巧&#xff01;pyzbar PI…...

用一个例子告诉你 怎样使用Spark中RDD的算子

目录 1. 前言 1.1 操作分类 1.2 语法知识 2. transformations 2.1 map 2.2 mapPartitions 2.3 flatMap 2.4 glom 2.5 groupBy 2.6 filter 2.7 sample 2.8 distinct 2.9 coalesce 2.10 repartition 2.11 sortBy 2.12 partitionBy 2.13 reduceByKey 2.14 gro…...

什么是跨域? 出现原因及解决方法

目录一、什么是跨域二、为什么有跨域问题&#xff1f;三、解决跨域问题的方案1.Jsonp2.nginx3.CORS3.1 什么是cors3.2 原理四、GateWay网关中实现跨域步骤一、什么是跨域 跨域&#xff1a;浏览器对于javascript的同源策略的限制 。 同源政策的目的&#xff0c;是为了保证用户…...

低代码系统能够解决哪些痛点?

低代码系统能够解决哪些痛点&#xff1f;如果用4句话去归纳&#xff0c;低代码开发可以解决以下问题—— 为企业提供更高的灵活性&#xff0c;用户可以突破代码的限制自主开发业务应用&#xff1b;通过减少对专业软件开发人员的依赖&#xff0c;公司可以快速响应市场上的新业务…...

华为OD机试题,用 Java 解【两数之和绝对值最小】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

AcWing算法提高课-3.1.1热浪

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 题目传送门点这里 题目描述 德克萨斯纯朴的民众们这个夏天正在遭受巨大的热浪&#xff01;&#xff01;&#xff01; 他们的德克萨斯长角牛吃起来不错&#xff0c;可是它们并不是很擅长生产富…...