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

电子商务网站建设影响因素/网站关键词优化怎么做的

电子商务网站建设影响因素,网站关键词优化怎么做的,app软件开发价目表,设计做网站文章目录 4.2.1 矩阵的数组表示4.2.2 特殊矩阵的压缩存储a. 对角矩阵的压缩存储b~c. 三角、对称矩阵的压缩存储d. 稀疏矩阵的压缩存储——三元组表e. 压缩稀疏行(Compressed Sparse Row,CSR)矩阵结构体创建CSR矩阵元素设置初始化打印矩阵销毁…

文章目录

  • 4.2.1 矩阵的数组表示
  • 4.2.2 特殊矩阵的压缩存储
    • a. 对角矩阵的压缩存储
    • b~c. 三角、对称矩阵的压缩存储
    • d. 稀疏矩阵的压缩存储——三元组表
    • e. 压缩稀疏行(Compressed Sparse Row,CSR)矩阵
      • 结构体
      • 创建CSR矩阵
      • 元素设置
      • 初始化
      • 打印矩阵
      • 销毁CSR矩阵
      • 主函数
      • 代码整合

4.2.1 矩阵的数组表示

【数据结构】数组和字符串(一):矩阵的数组表示

4.2.2 特殊矩阵的压缩存储

  矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造成很大的空间浪费。为节约存储空间和算法(程序)运行时间,通常会采用压缩存储的方法。

  • 对角矩阵:指除了主对角线以外的元素都为零的矩阵,即对 任意 i ≠ j (1≤ i , j ≤n),都有M(i, j)=0。由于只有主对角线上有非零元素,只需存储主对角线上的元素即可。
  • 三角矩阵:指上三角或下三角的元素都为零的矩阵。同样地,只需存储其中一部分非零元素,可以节省存储空间。
  • 对称矩阵:指矩阵中的元素关于主对角线对称的矩阵。由于对称矩阵的非零元素有一定的规律,可以只存储其中一部分元素,从而减少存储空间。
  • 稀疏矩阵:指大部分元素为零的矩阵。传统的按行优先次序存储方法会浪费大量空间来存储零元素,因此采用压缩存储的方法更为合适。常见的压缩存储方法有:压缩稠密行(CSR)、压缩稠密列(CSC)、坐标列表(COO)等。

a. 对角矩阵的压缩存储

【数据结构】数组和字符串(二):特殊矩阵的压缩存储:对角矩阵——一维数组

b~c. 三角、对称矩阵的压缩存储

【数据结构】数组和字符串(三):特殊矩阵的压缩存储:三角矩阵、对称矩阵——一维数组

d. 稀疏矩阵的压缩存储——三元组表

【数据结构】数组和字符串(四):特殊矩阵的压缩存储:稀疏矩阵——三元组表

e. 压缩稀疏行(Compressed Sparse Row,CSR)矩阵

  压缩稀疏行(Compressed Sparse Row,CSR)是一种常用的稀疏矩阵存储格式。CSR存储格式通过压缩非零元素的行指针和列索引,以及存储非零元素的值,来有效地表示稀疏矩阵。它包含以下几个关键组成部分:

  • row_ptr(行指针数组):它是一个长度为rows + 1的数组,用于存储每一行在col_indices和elements数组中的起始索引位置。row_ptr[i]表示第i行的元素在col_indices和elements数组中的起始位置,而row_ptr[i+1] - row_ptr[i]表示第i行的非零元素个数。
  • col_indices(列索引数组):它是一个长度为num_elements的数组,用于存储每个非零元素对应的列索引。col_indices[i]表示第i个非零元素所在的列索引。
  • elements(元素数组):它是一个长度为num_elements的数组,用于存储每个非零元素的值。elements[i]表示第i个非零元素的值。

  CSR存储格式的主要优点是有效地压缩了稀疏矩阵的存储空间,只存储非零元素及其对应的行和列信息。此外,CSR格式还支持高效的稀疏矩阵向量乘法和稀疏矩阵乘法等操作。

结构体

typedef struct {int row;int col;int value;
} Element;typedef struct {int rows;int cols;int num_elements;Element* elements;int* row_ptr;int* col_indices;
} CSRMatrix;
  • Element 结构体表示矩阵中的一个元素,包含三个成员变量:row(行索引)、col(列索引)和 value(元素值)。

  • CSRMatrix 结构体表示一个CSR矩阵,包含了矩阵的行数 rows、列数 cols、非零元素的个数 num_elements,以及三个指针成员变量 elementsrow_ptrcol_indices

创建CSR矩阵

CSRMatrix createCSRMatrix(int rows, int cols, int num_elements) {CSRMatrix matrix;matrix.rows = rows;matrix.cols = cols;matrix.num_elements = num_elements;matrix.elements = (Element*)malloc(num_elements * sizeof(Element));matrix.row_ptr = (int*)malloc((rows + 1) * sizeof(int));matrix.col_indices = (int*)malloc(num_elements * sizeof(int));return matrix;
}
  • createCSRMatrix 函数用于创建一个CSR矩阵。
  • 接受矩阵的行数、列数和非零元素的个数作为参数,并返回创建的CSR矩阵。
  • 在函数内部,通过动态内存分配分别为 elementsrow_ptrcol_indices 分配内存空间,并将 row_ptr 数组的所有元素初始化为0,最后返回创建的矩阵。

元素设置

void setElement(CSRMatrix* matrix, int row, int col, int value) {if (row < 0 || row >= matrix->rows) {printf("Invalid row index.\n");return;}int index = matrix->row_ptr[row];matrix->elements[index].row = row;matrix->elements[index].col = col;matrix->elements[index].value = value;matrix->col_indices[index] = col;matrix->row_ptr[row]++;  // 递增索引值
}

  setElement 函数可用于设置(修改)CSR矩阵中某个位置的元素值。

  • 接受一个指向CSR矩阵的指针 matrix,以及要设置的元素的行索引、列索引和值作为参数。
  • 在函数内部,首先检查行索引是否有效,如果无效则打印错误信息并返回。
  • 然后,根据行索引找到对应行的起始位置,将元素的行索引、列索引和值分别赋给对应的矩阵元素,并更新 col_indices 数组和 row_ptr 数组中的值。

初始化

void initializeCSRMatrix(CSRMatrix* matrix, int* values, int* row_indices, int* col_indices, int num_elements) {for (int i = 0; i < num_elements; i++) {matrix->elements[i].value = values[i];matrix->elements[i].row = row_indices[i];matrix->elements[i].col = col_indices[i];matrix->col_indices[i] = col_indices[i];matrix->row_ptr[row_indices[i]]++;}int sum = 0;for (int i = 0; i <= matrix->rows; i++) {int temp = matrix->row_ptr[i];matrix->row_ptr[i] = sum;sum += temp;}
}

  initializeCSRMatrix 函数用于初始化CSR矩阵的数据。

  • 接受一个指向CSR矩阵的指针 matrix,以及包含非零元素的值、行索引和列索引的数组,以及非零元素的个数作为参数。
  • 通过遍历非零元素数组,将值、行索引和列索引分别赋给对应的矩阵元素,并更新 col_indices 数组和 row_ptr 数组中的值。row_ptr 数组的每个元素表示对应行的非零元素在 elements 数组中的起始位置,通过累加非零元素的个数来计算每行的结束位置。

打印矩阵

void printCSRMatrix(CSRMatrix matrix) {printf("CSR Matrix:\n");printf("Rows: %d, Cols: %d, Num Elements: %d\n", matrix.rows, matrix.cols, matrix.num_elements);printf("Values: ");for (int i = 0; i < matrix.num_elements; i++) {printf("%d ", matrix.elements[i].value);}printf("\n");printf("Row Pointer: ");for (int i = 0; i <= matrix.rows; i++) {printf("%d ", matrix.row_ptr[i]);}printf("\n");printf("Column Indices: ");for (int i = 0; i < matrix.num_elements; i++) {printf("%d ", matrix.col_indices[i]);}printf("\n");
}
void printMatrixForm(CSRMatrix matrix) {printf("Matrix Form:\n");for (int i = 0; i < matrix.rows; i++) {for (int j = 0; j < matrix.cols; j++) {int value = 0;for (int k = matrix.row_ptr[i]; k < matrix.row_ptr[i + 1]; k++) {if (matrix.elements[k].col == j) {value = matrix.elements[k].value;break;}}printf("%d ", value);}printf("\n");}
}
  • printCSRMatrix 函数用于打印CSR矩阵的信息:它接受一个CSR矩阵作为参数,并打印矩阵的行数、列数、非零元素的个数以及 elementsrow_ptrcol_indices 数组的内容。
  • printMatrixForm 函数用于以矩阵形式打印CSR矩阵。它接受一个CSR矩阵作为参数,并按矩阵的行数和列数遍历矩阵元素,通过遍历 row_ptr 数组和 col_indices 数组来获取每个位置的元素值,并打印出矩阵的形式。

销毁CSR矩阵

void destroyCSRMatrix(CSRMatrix* matrix) {free(matrix->elements);free(matrix->row_ptr);free(matrix->col_indices);matrix->elements = NULL;matrix->row_ptr = NULL;matrix->col_indices = NULL;
}

主函数

int main() {int rows = 9;int cols = 3;int num_elements = 5;CSRMatrix matrix = createCSRMatrix(rows, cols, num_elements);int col_indices[] = {0, 0, 0, 0, 1};int row_indices[] = {3, 5, 7, 8, 7};int values[] =      {2, 1, 3, 1, 4};initializeCSRMatrix(&matrix, values, row_indices, col_indices, num_elements);printCSRMatrix(matrix);printMatrixForm(matrix);destroyCSRMatrix(&matrix);return 0;
}

在这里插入图片描述

代码整合

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct {int row;int col;int value;
} Element;typedef struct {int rows;int cols;int num_elements;Element* elements;int* row_ptr;int* col_indices;
} CSRMatrix;CSRMatrix createCSRMatrix(int rows, int cols, int num_elements) {CSRMatrix matrix;matrix.rows = rows;matrix.cols = cols;matrix.num_elements = num_elements;matrix.elements = (Element*)malloc(num_elements * sizeof(Element));matrix.row_ptr = (int*)malloc((rows + 1) * sizeof(int));matrix.col_indices = (int*)malloc(num_elements * sizeof(int));memset(matrix.row_ptr, 0, (rows + 1) * sizeof(int));return matrix;
}
void initializeCSRMatrix(CSRMatrix* matrix, int* values, int* row_indices, int* col_indices, int num_elements) {for (int i = 0; i < num_elements; i++) {matrix->elements[i].value = values[i];matrix->elements[i].row = row_indices[i];matrix->elements[i].col = col_indices[i];matrix->col_indices[i] = col_indices[i];matrix->row_ptr[row_indices[i]]++;}int sum = 0;for (int i = 0; i <= matrix->rows; i++) {int temp = matrix->row_ptr[i];matrix->row_ptr[i] = sum;sum += temp;}
}void setElement(CSRMatrix* matrix, int row, int col, int value) {if (row < 0 || row >= matrix->rows) {printf("Invalid row index.\n");return;}int index = matrix->row_ptr[row];matrix->elements[index].row = row;matrix->elements[index].col = col;matrix->elements[index].value = value;matrix->col_indices[index] = col;matrix->row_ptr[row]++;  // 递增索引值
}void printCSRMatrix(CSRMatrix matrix) {printf("CSR Matrix:\n");printf("Rows: %d, Cols: %d, Num Elements: %d\n", matrix.rows, matrix.cols, matrix.num_elements);printf("Values: ");for (int i = 0; i < matrix.num_elements; i++) {printf("%d ", matrix.elements[i].value);}printf("\n");printf("Row Pointer: ");for (int i = 0; i <= matrix.rows; i++) {printf("%d ", matrix.row_ptr[i]);}printf("\n");printf("Column Indices: ");for (int i = 0; i < matrix.num_elements; i++) {printf("%d ", matrix.col_indices[i]);}printf("\n");
}
void printMatrixForm(CSRMatrix matrix) {printf("Matrix Form:\n");for (int i = 0; i < matrix.rows; i++) {for (int j = 0; j < matrix.cols; j++) {int value = 0;for (int k = matrix.row_ptr[i]; k < matrix.row_ptr[i + 1]; k++) {if (matrix.elements[k].col == j) {value = matrix.elements[k].value;break;}}printf("%d ", value);}printf("\n");}
}void destroyCSRMatrix(CSRMatrix* matrix) {free(matrix->elements);free(matrix->row_ptr);free(matrix->col_indices);matrix->elements = NULL;matrix->row_ptr = NULL;matrix->col_indices = NULL;
}int main() {int rows = 9;int cols = 3;int num_elements = 5;CSRMatrix matrix = createCSRMatrix(rows, cols, num_elements);int col_indices[] = {0, 0, 0, 0, 1};int row_indices[] = {3, 5, 7, 8, 7};int values[] =      {2, 1, 3, 1, 4};initializeCSRMatrix(&matrix, values, row_indices, col_indices, num_elements);printCSRMatrix(matrix);printMatrixForm(matrix);destroyCSRMatrix(&matrix);return 0;
}

相关文章:

【数据结构】数组和字符串(五):特殊矩阵的压缩存储:稀疏矩阵——压缩稀疏行(CSR)

文章目录 4.2.1 矩阵的数组表示4.2.2 特殊矩阵的压缩存储a. 对角矩阵的压缩存储b~c. 三角、对称矩阵的压缩存储d. 稀疏矩阵的压缩存储——三元组表e. 压缩稀疏行&#xff08;Compressed Sparse Row&#xff0c;CSR&#xff09;矩阵结构体创建CSR矩阵元素设置初始化打印矩阵销毁…...

springboot整合postgresql

使用docker安装postgres 简单起见&#xff0c;这里用docker来安装postgresql docker pull postgresdocker run --name postgres \-e POSTGRES_PASSWORD123456 \-p 5432:5432 \-v /usr/local/docker/postgresql/data:/var/lib/postgresql/data \-d postgrespostgres客户端 pg…...

C#__委托delegate

委托存储的是函数的引用&#xff08;把某个函数赋值给一个委托类型的变量&#xff0c;这样的话这个变量就可以当成这个函数来进行使用了&#xff09; 委托类型跟整型类型、浮点型类型一样&#xff0c;也是一种类型&#xff0c;是一种存储函数引用的类型 using System.Reflec…...

Jupyter Notebook的安装方法以及生成ipykernel

1. 安装Python和pip Jupyter Notebook是基于Python的&#xff0c;因此首先需要在电脑上安装Python和pip。可以通过访问Python官网(Welcome to Python.org)下载安装包进行安装。在安装Python的过程中&#xff0c;会提示是否安装pip&#xff0c;选择安装即可。 2. 安装Jupyter …...

测试员如何快速复现bug?一款合适的视频录制软件了解一下

你是不是还在为描述缺陷复现步骤而苦恼&#xff1f;你是不是还在为寻找一款合适的视屏录制软件而挣扎&#xff1f;那么&#xff0c;你应该好好看看这篇小文章。 作为测试人员&#xff0c;撰写测试用例、提交测试缺陷是基本工作。但往往我们会遇到&#xff1a;开发人员无法根据…...

论文-分布式-并发控制-并发控制问题的解决方案

目录 参考文献 问题 解法与证明 易读版本 参考文献 Dijkstra于1965年发表文章Solution of a Problem in Concurrent Programming Control&#xff0c;引出并发系统下的互斥(mutual exclusion)问题&#xff0c;自此开辟了分布式计算领域Dijkstra在文中给出了基于共享存储原子…...

【网络协议】聊聊http协议

当我们输入www.baidu.com的时候&#xff0c;其实是先将baidu.com的域名进行DNS解析&#xff0c;转换成对应的ip地址&#xff0c;然后开始进行基于TCP构建三次握手的连接&#xff0c;目前使用的是1.1 默认是开启了keep-Alive。可以在多次请求中进行连接复用。 HTTP 请求的构建…...

图神经网络论文笔记(一)——北邮:基于学习解纠缠因果子结构的图神经网络去偏

作者 &#xff1a;范少华 研究方向 &#xff1a;图神经网络 论文标题 &#xff1a;基于学习解纠缠因果子结构的图神经网络去偏 论文链接 &#xff1a;https://arxiv.org/pdf/2209.14107.pdf        https://doi.org/10.48550/arXiv.2209.14107 大多数图神经网络(GNNs)通…...

java初始化list的几种方式

在Java中初始化List有以下几种常见的方式: 使用Arrays.asList()静态方法: List<Integer> list1 Arrays.asList(1, 2, 3);使用List接口的实现类ArrayList的构造函数: List<String> list2 new ArrayList<>();使用Collections.singletonList() String obj…...

Linux:文件操作

目录 一、关于文件 1、文件类的系统接口 2、文件的含义 二、文件操作 1、C语言文件相关接口 2、系统接口 open close write read 三、文件描述符 关于fd fd的分配规则 输出重定向示例 输入重定向示例 追加重定向示例 dup2函数 缓冲区 stdout与stderr perror…...

vue源码笔记之——运行时runtime

源码中的位运算 按位于 运算 if (shapeFlag & ShapeFlags.TELEPORT) {解释&#xff1a;如果shapFlag本身值为8&#xff0c;type为1的话&#xff0c;那么转换为二进制&#xff08;js都是32位&#xff09;那就是 shapFlag&#xff1a;00000000 00000000 00000000 00001000 …...

MySQL数据库干货_09—— MySQL中的外键约束(Foreign Key)

外键约束(Foreign Key) 添加外键约束 使用DDL语句添加外键约束 ALTER TABLE 表名 ADD CONSTRAINT 约束名 FOREIGN KEY( 列 名 ) REFERENCES 参照的表名(参照的列名);示例一&#xff1a; 创建 departments 表包含 department_id 、department_name &#xff0c;location_id。…...

springboot配置https

SSL &#xff1a; secure socket layer 是一种加密协议&#xff0c;SSL主要用于保护数据在 客户端和服务器之间的传输&#xff0c;&#xff0c;防止未经授权的访问和窃取敏感信息 在腾讯云申请ssl证书 申请了之后在我的域名中&#xff0c;&#xff0c;解析 解析了之后&…...

java - IDEA IDE - 设置字符串断点

文章目录 java - IDEA IDE - 设置字符串断点概述笔记END java - IDEA IDE - 设置字符串断点 概述 IDE环境为IDEA2022.3 在看一段序列化的代码, 想找出报错抛异常那个点, 理解一下代码实现. 因为序列化代码实现在第三方jar包中, 改不了(只读的). 根本数不清第几次才会开始报…...

【图像分类】基于计算机视觉的坑洼道路检测和识别(ResNet网络,附代码和数据集)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。(专栏订阅用户订阅专栏后免费提供数据集和源码一份,超级VIP用户不在服务范围之内,不想订阅专栏的兄弟们可以私信…...

关于readline方法使用的一个中文乱码引发的思考

故事起源于这段代码&#xff0c;我想给一个本地地址然后去读取文件内容&#xff0c;然后使用了reader.readLine();方法&#xff0c;但是本地没有任何报错&#xff0c;但是线上中文乱码导致直接报错了。 BufferedReader reader;try {reader new BufferedReader(new FileReader(…...

BUUCTF 神秘龙卷风 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 神秘龙卷风转转转&#xff0c;科学家用四位数字为它命名&#xff0c;但是发现解密后居然是一串外星人代码&#xff01;&#xff01;好可怕&#xff01; 密文&#xff1a; 下载附件&#xff0c;解压得到一个.rar压缩…...

【JavaEE初阶】 认识文件与Java中操作文件

文章目录 &#x1f334;认识文件&#x1f6a9;树型结构组织和目录&#x1f6a9;文件路径&#xff08;Path&#xff09;&#x1f6a9;知识扩展 &#x1f38d;Java 中操作文件&#x1f6a9;File 概述&#x1f4cc;属性&#x1f4cc;构造方法&#x1f4cc;方法 &#x1f6a9;File使…...

数据结构───链表

花费一个周时间学完了链表&#xff08;的一部分&#xff09;&#xff0c;简单总结一下。 链表的学习离不开画图&#xff0c;将其抽象成一种逻辑模型&#xff0c;可以减少思考时间&#xff0c;方便理解。 链表大致分为8种结构&#xff0c;自己学习并实现了两种结构&#xff0c;也…...

SQLAlchemy删除所有重复的用户|Counter类运用

Python标准库中的collections模块中的Counter类。Counter类用于计算可迭代对象中元素的出现次数&#xff0c;并以字典的形式返回结果&#xff0c;其中键是元素&#xff0c;值是该元素的出现次数。 for name, count in Counter(names).items() 是一个循环语句&#xff0c;它用于…...

Lec11 Thread switching (Robert)

线程的概念 线程就是单个串行执行代码的单元&#xff0c;它只占用一个CPU并且以普通的方式一个接一个的执行指令。 线程还具有状态&#xff0c;我们可以随时保存线程的状态并暂停线程的运行&#xff0c;并在之后通过恢复状态来恢复线程的运行。 程序计数器&#xff08;Progr…...

前端的简单介绍

前端核心的分析 CSS语法不够强大&#xff0c;比如无法嵌套书写&#xff0c;倒是模块化开发中需要书写很多重复的选择器 没有变量和合理的样式复用机制&#xff0c;使逻辑上相关的属性值必须字面量的心事重复的输出&#xff0c;导致难以维护 CSS预处理器,减少代码的笨重&#…...

云服务器 centos 部署 code-server 并配置 c/c++ 环境

将你的云服务器改为 centos 8 为什么要将云服务器的操作系统改成 centos 8 呢&#xff1f;原因就是 centos 7 里面的配置满足不了 code-server 的需求。如果你使用的是 centos 7 那么就需要你升级一些东西&#xff0c;这个过程比较麻烦。我在 centos 7 上面运行 code-server 的…...

Ubuntu 22.04 安装 Terraform

Ubuntu 22.04 安装 Terraform 安装 Terraform 安装 Terraform sudo apt updatesudo apt install software-properties-common gnupg2 curlcurl https://apt.releases.hashicorp.com/gpg | gpg --dearmor > hashicorp.gpgsudo install -o root -g root -m 644 hashicorp.gpg…...

MLF - 麻辣粉

MLF全称中期借贷便利&#xff08;Medium-term lending Facility&#xff09;,理解为央行向商业银行、政策银行发放的贷款&#xff0c;但需要符合一定要求才可向央行申请。银行通过MLF向央行借款的时候&#xff0c;需要提供担保品。一般为国债、央行票据、政策性金融债、地方债、…...

Flutter三棵树的创建流程

一、Flutter常见的家族成员 Widget常见的家族成员 Element常见的家族成员 Render常见的家族成员 二、示例代码对应的Flutter Inspector树 示例代码&#xff1a;MyApp->MyHomePage->ErrorWidget&#xff0c;包含了StatelessWidget、StatefulWidget、LeafRenderObjectWid…...

思维训练第二课 独立主格

系列文章目录 文章目录 系列文章目录前言一、独立主格特点 二、独立主格的构成1.名词/人称代词主格现在分词2. 名词/人称代词主格过去分词3. 名词/人称代词主格形容词/副词4. 名词/人称代词主格不定式5. 名词/人称代词主格介词短语6.介词复合宾语 三、独立主格结构的句法功能1、…...

一致性哈希揭秘,深入解析其工作原理

前言 在进行一致性哈希介绍前&#xff0c;先思考2个问题&#xff1a; 什么是Hash一致性Hash和Hash的关系是什么 对于第一个问题Hash的定义 Hash也成散列&#xff0c;基本原理就是把任意长度的输入&#xff0c;通过hash算法变成固定长度的输出。 对于第二个问题&#xff0c…...

前端环境的安装 Node npm yarn

一 node npm 1.下载NodeJS安装包 下载地址&#xff1a;Download | Node.js 2.开始安装 打开安装包后&#xff0c;一直Next即可。当然&#xff0c;建议还是修改一下安装位置&#xff0c;NodeJS默认安装位置为 C:\Program Files 3.验证是否安装成功 打开DOS命令界面&#…...

基于机器视觉的银行卡识别系统 - opencv python 计算机竞赛

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的银行卡识别算法设计 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng…...