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

「数据结构」线性表

定义和基本操作

  1. 定义:相同数据类型的 n ( n ≥ 0 ) n(n \ge 0) n(n0)个数据元素的有限序列,其中n为表长,当n=0时线性表是一个空表
  2. 一般表示: L = ( a 1 , a 2 , … … , a i , a i + 1 , a n ) L=(a_1,a_2,……,a_i,a_{i+1},a_n) L=(a1,a2,……,ai,ai+1,an)
    1. a 1 a_1 a1是表头元素, a n a_n an是表尾元素
  3. 除第一个元素外,每个元素有且只有一个直接前驱;除最后一个元素外,每个元素有且只有一个直接后继

基本操作

  1. InitList(&L);初始化表。构造一个空的线性表L,分配内存空间
  2. DestroyList(&L):销毁操作。销毁线性表,并释放线性表L所占用的内存空间
  3. ListInsert(&L,i,e):插入操作。在表L中的第i个位置插入指定元素e
  4. ListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值
  5. LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素
  6. GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值

其他常用操作

  1. Length(L):求表长。返回线性表L中数据元素的个数
  2. PrintList(L):输出操作。按前后顺序输出线性表L的所有元素值
  3. Empty(L):判空操作。若L为空表,返回true,否则返回false

顺序表

定义

  1. 顺序表:用顺序存储的方式实现线性表的顺序存储。把逻辑上相邻的元素存储在物理位置也相邻的存储单元中
  2. 顺序表的实现-静态分配
#define MaxSize 50		//线性表的最大长度typedef struct {ElemType data[MaxSize];	//顺序表的元素int length;			//顺序表的当前长度
}SqList;				//顺序表的类型定义
  1. 顺序表的实现-动态分配
    1. 时间开销大
#define InitSize 50		//顺序表的初始长度
//动态分配
typedef struct {ElemType* data;	//指针动态分配数组的指针int maxsize;	//顺序表的最大容量int length;	//顺序表的当前长度
}SeqList;
  1. 动态申请和释放内存空间
    1. C:malloc、free函数

L.data = (ElemType*)malloc(sizeof(ElemType) * InitSize); //C语言初始动态分配

	2. C++:new、delete关键字```C++
L.data = new int[InitSize];
  1. 顺序表的特点
    1. 随机访问,可以在O(1)时间内找到第i个元素
    2. 存储密度高
    3. 拓展容量不方便
    4. 插入、删除操作不方便,需要移动大量元素

插入和删除

插入

  1. ListInsert(&L,i,e):插入操作。在表L中第i个位置上插入指定元素
bool ListInsert(SqList& L, int i, int e){if (i<1 || i>L.length + 1) {	//判断i的范围是否有效return false;}if (L.length >= MaxSize) {	//当前存储空间已满,不能插入return false;}for (int j = L.length; j >= i; j--) {	//将第i个元素及之后的元素后移L.data[j] = L.data[j - 1];}L.data[i - 1] = e;	//在位置i处放eL.length++;	//长度加1return true;
}
  1. 时间复杂度
    1. 最好情况:在表尾插入(即i=n+1),不需要移动元素,时间复杂度为O(1)
    2. 最坏情况:在表头插入(即i=1),元素后移语句执行n次,时间复杂度为O(n)
    3. 平均情况:移动结点的平均次数 n 2 \frac{n}{2} 2n,时间复杂度O(n)

删除

bool ListDelete(SqList& L, int i, int& e){if (i<1 || i>L.length + 1) {	//判断i的范围是否有效return false;}e = L.data[i - 1];	//将被删除的元素赋值给efor (int j = i; j < L.length; j++) {	//将第i个位置后的元素前移L.data[j - 1] = L.data[j];}L.length--;	线性表长度减1return true;
}
  1. 时间复杂度
    1. 最好情况:删除表尾元素(即i=n),时间复杂度为O(1)
    2. 最坏情况:删除表头元素(即i=1),时间复杂度为O(n)
    3. 平均情况:移动结点的平均次数 n − 1 2 \frac{n-1}{2} 2n1,时间复杂度O(n)

查找

按位查找

  1. GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值
int GetElem(SqList L, int i){return L.data[i - 1];
}int GetElem(SeqList L, int i){return L.data[i - 1];
}
  1. 时间复杂度O(1)
    1. 随机存取特性

按值查找

  1. LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素
int LoacteElem(SqList L, int e){int i;for (i = 0; i < L.length; i++) {if (L.data[i] == e) {    //"=="不可以用于比较两个结构体return i + 1;	//下标为i的元素值等于e,返回其位序i+1}}return 0;	//退出循环,说明查找失败
}
  1. 时间复杂度
    1. 最好情况:查找的元素在表头,时间复杂度为O(1)
    2. 最坏情况:查找的元素在表尾(或不存在),时间复杂度为O(n)
    3. 平均情况:平均比较次数 n + 1 2 \frac{n+1}{2} 2n+1,时间复杂度为O(n)

单链表

定义

typedef struct LNode {	//定义单链表结点类型int data;	//每个结点存放一个指针元素struct LNode* next;	//指针指向下一个结点
}LNode, * LinkList;
  1. 不带头结点的单链表
bool InitList(LinkList& L){L = NULL;	//空表,暂时没有任何结点return true;
}
  1. 带头结点的单链表
bool InitList(LinkList& L) {L = (LNode*)malloc(sizeof(LNode));	//分配一个头结点if (L == NULL) {return false;}L -> next = NULL;	//头结点之后暂时还没有结点return true;
}

插入和删除

按位序插入(带头结点)

  1. ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList &L, int i, ElemType e){if(i<1){return false;}LNode *p;    //指针p指向当前扫描的结点int j=0;    //当前p指向的是第几个结点p=L;    //L指向头结点,头结点是第0个结点(不存储数据)while(p!=NULL && j<i-1){    //循环找到第i-1个结点p=p->next;j++;}if(p==NULL){    //i值不合法return false;}LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;p-next=s;    //将结点s连到p之后return true;    //插入成功
}

按位序插入(不带头结点)

  1. ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList &L, int i, ElemType e){if(i<1){return false;}if(i==1){    //插入第i个结点的操作与其他结点不同LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=L;L=s;    //头指针指向新结点return true;    //插入成功}LNode *p;    //指针p指向当前扫描的结点int j=1;    //当前p指向的是第几个结点p=L;    //p指向第1个结点(不是头结点)while(p!=NULL && j<i-1){    //循环找到第i-1个结点p=p->next;j++;}if(p==NULL){    //i值不合法return false;}LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;p-next=s;    //将结点s连到p之后return true;    //插入成功
}

指定结点的后插操作

//在p结点之后插入元素e
bool InsertNextNode(LNode *p, ElemType e){if(p==NULL){return false;}LNode *s=(LNode *)malloc(sizeof(LNode));if(s==NULL){    //内存分配失败return false;}s->data=e;    //用结点s保存数据元素es->next=p->next;p->next=s;    //将结点s连接到p之后return true;
}

指定元素的前插操作

//在p结点之前插入元素e
bool InsertPriorNode(LNode *p, ElemType e){if(p==NULL){return false;}LNode *s=(LNode *)malloc(sizeof(LNode));if(s==NULL){    //内存分配失败return false;}s->next=p->next;p->next=s;    //将结点s连接到p之后s->data=p->data;    //将p中的元素复制到s中p->data=e;    //p中元素覆盖为ereturn true;
}

按位序删除(带头结点)

  1. ListDelete(&L,i,&e);删除操作,删除表L中第i个位置的元素,并用e返回元素的值
bool ListDelete(LinkList &L,int i,ElemType &e){if(i<1){return false;}LNode *p;    //指针p指向当前扫描到的结点int j=0;    //当前p指向的是第几个结点p=L;    //L指向头结点,头结点是第0个结点 (不存数据)while (p!=NULL & j<i-1){    //循环找至第 i-1个结点p=p->next;j++;}if(p==NULL){    //i值不合法return false;}if(p->next == NULL){    //第i-1个结点之后已无其他结点return false;}LNode *q=p->next;    //令q指向被删除结点e = q->data;    //用e返回元素的值p->next=q->next;    //将*q结点从链中“断开”free(q);    //释放结点的存储空间return true;    //删除成功
}

指定结点的删除

//删除指定结点p
bool DeleteNode (LNode *p){if (p==NULL){return false;}LNode *q=p->next;    //令q指向*p的后继结点p->data=p->next->data;    //和后继结点交换数据域p->next=q->next;    //将*q结点从链中“断开”free(q);    //释放后继结点的存储空间return true;
}

如果p是最后一个结点,只能从表头开始寻找p的前驱,时间复杂度O(n)

查找

按位查找

  1. GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值
//按位查找,返回第i个元素(带头结点)
LNode *GetElem(LinkList, int i){if(i<0){return NULL;}LNode *p;    //指针p指向当前扫描到的结点int j=0;    //当前p指向的是第几个结点p=L;    //L指向头结点,头结点是第0个结点(不存储数据)while (p!=NULL && j<i){    //循环找到第 i 个结点p=p->next;j++;}return p;
}
  1. 平均时间复杂度O(n)

按值查找

  1. LocateElem(L,i):按值查找操作。在表L中查找具有给定关键字值的元素
//按值查找,找到数据域==e 的结点
LNode * LocateElem(LinkList L,ElemType e){LNode *p = L->next;//从第1个结点开始查找数据域为e的结点while (p != NULL && p->data != e)p = p->next;return p;    //找到后返回该结点指针,否则返回NULL
}
  1. 时间复杂度O(n)

求表的长度

//求表的长度
int Length(LinkList L){int len = 0;    //统计表长LNode *p = L;while (p->next != NULL){p = p->next;len++;}return len;
  1. 时间复杂度O(n)

建立

  1. 尾插法
  2. 头插法

双链表

  1. 初始化
  2. 插入
  3. 删除
  4. 遍历

循环链表

  1. 循环单链表:表尾结点的next指针指向头结点
    1. 从一个结点出发可以找到其他任何一个结点
  2. 循环双链表

静态链表

  1. 概念:分配一整连续的内存空间,各个结点集中安置

顺序表和链表的比较

  1. 逻辑结构
    1. 都属于线性表,都是线性结构
  2. 物理结构/存储结构
    1. 顺序表
      1. 优点:支持随机存取、存取密度高
      2. 缺点:大片连续空间分配不方便,改变容量不方便
    2. 链表
      1. 优点:离散的小空间分配方便、改变容量方便
      2. 缺点:不可随机存取、存取密度低
  3. 数据的运算/基本操作
    1. 初始化
      1. 顺序表:需要预分配大片连续空间若分配空间过小,则之后不方便拓展容量;若分配空间过大,则浪费内存资源
        1. 静态分配:静态数组,容量不可改变
        2. 动态分配:动态数组(malloc、free),容量可改变,但需要移动大量元素,时间代价高
      2. 链表:只需分配一个头结点 (也可以不要头结点,只声明一个头指针) ,之后方便拓展
    2. 销毁
      1. 顺序表:修改Length=0
        1. 静态分配:系统自动回收空间
        2. 动态分配:需要手动free
      2. 链表:依次删除各个结点(free)
    3. 插入和删除
      1. 顺序表:需要把后续元素后移/前移,若数据元素很大,则移动的时间代价很大
      2. 链表:修改指针
    4. 查找
      1. 顺序表
        1. 按位查找:O(1)
        2. 按值查找:O(n)
          1. 若表内元素有序,可在 O ( l o g 2 n ) O(log_2n) O(log2n)时间内找到
      2. 链表
        1. 按位查找:O(n)
        2. 按值查找:O(n)

开放式问题回答思路

问题: 请描述顺序表和链表的 bla bla bla… 实现线性表时,用顺序表还是链表好?

顺序表和链表的逻辑结构都是线性结构,都属于线性表但是二者的存储结构不同,顺序表采用顺序存储…(特点,带来的优点缺点): 链表采用链式存储…(特点、导致的优缺点)。由于采用不同的存储方式实现,因此基本操作的实现效率也不同。当初始化时…;当插入一个数据元素时…;当删除一个数据元素时…; 当查找一个数据元素时…

相关文章:

「数据结构」线性表

定义和基本操作 定义&#xff1a;相同数据类型的 n ( n ≥ 0 ) n(n \ge 0) n(n≥0)个数据元素的有限序列&#xff0c;其中n为表长&#xff0c;当n0时线性表是一个空表一般表示&#xff1a; L ( a 1 , a 2 , … … , a i , a i 1 , a n ) L(a_1,a_2,……,a_i,a_{i1},a_n) L(a…...

GEE:关于在GEE平台上进行回归计算的若干问题

作者&#xff1a;CSDN _养乐多_ 记录一些在Google Earth Engine &#xff08;GEE&#xff09;平台上进行机器学习回归计算的问题和解释。 文章目录 一、回归1.1 问&#xff1a;GEE平台上可以进行哪些机器学习回归算法&#xff1f;1.2 问&#xff1a;为什么只有这四种&#xf…...

Vivado -RAM

ip_ram 定义了一个名为ip_ram的模块&#xff0c;该模块具有以下端口&#xff1a; sys_clk&#xff1a;系统时钟输入。 sys_rst_n&#xff1a;系统复位输入。 module ip_ram( input sys_clk, input sys_rst_n);wire ram_en ; wire ram_wea …...

备战蓝桥杯---图论之最短路dijkstra算法

目录 先分个类吧&#xff1a; 1.对于有向无环图&#xff0c;我们直接拓扑排序&#xff0c;和AOE网类似&#xff0c;把取max改成min即可。 2.边权全部相等&#xff0c;直接BFS即可 3.单源点最短路 从一个点出发&#xff0c;到达其他顶点的最短路长度。 Dijkstra算法&#x…...

C#系列-C#实现秒杀功能(14)

在C#中实现商品秒杀功能&#xff0c;通常需要考虑并发控制、数据库事务、缓存策略、限流措施等多个方面。下面是一个简单的示例&#xff0c;演示了如何使用C#和数据库来实现一个基本的商品秒杀功能。 首先&#xff0c;假设你有一个商品表&#xff08;Product&#xff09;和一个…...

Java ‘Elasticsearch‘ 操作

依赖 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-elasticsearch --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</ar…...

【AI视野·今日NLP 自然语言处理论文速览 第七十八期】Wed, 17 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 17 Jan 2024 (showing first 100 of 163 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Deductive Closure Training of Language Models for Coherence, Accur…...

实验5-4 使用函数计算两点间的距离

本题要求实现一个函数&#xff0c;对给定平面任意两点坐标(x1​,y1​)和(x2​,y2​)&#xff0c;求这两点之间的距离。 函数接口定义&#xff1a; double dist( double x1, double y1, double x2, double y2 );其中用户传入的参数为平面上两个点的坐标(x1, y1)和(x2, y2)&…...

【JavaEE】_JavaScript(Web API)

目录 1. DOM 1.1 DOM基本概念 1.2 DOM树 2. 选中页面元素 2.1 querySelector 2.2 querySelectorAll 3. 事件 3.1 基本概念 3.2 事件的三要素 3.3 示例 4.操作元素 4.1 获取/修改元素内容 4.2 获取/修改元素属性 4.3 获取/修改表单元素属性 4.3.1 value&#xf…...

ARM交叉编译搭建SSH

首先搭建好arm-linux交叉编译环境&#xff0c;开发板和主机可以ping通。 一、下载需要的源码 下载zlib: zlib-1.2.3.tar.gz 下载ssl: openssl-0.9.8d.tar.gz 下载ssh: openssh-4.6p1.tar.gz 二、交叉编译 新建目录/home/leo/ssh&#xff0c;并且将三个源码复制到该目录下。…...

###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步。 目录 一. 延时函数的生成 1.通过延时计算器得到延时函数 2.可赋值改变…...

回归预测模型:MATLAB多项式回归

1. 多项式回归模型的基本原理 多项式回归是线性回归的一种扩展&#xff0c;用于分析自变量 X X X与因变量 Y Y Y之间的非线性关系。与简单的线性回归模型不同&#xff0c;多项式回归模型通过引入自变量的高次项来增加模型的复杂度&#xff0c;从而能够拟合数据中的非线性模式。…...

「计算机网络」数据链路层

数据链路层的地位&#xff1a;网络中的主机、路由器等都必须实现数据链路层信道类型 点对点信道&#xff1a;使用一对一的点对点通信方式广播信道 使用一对多的广播通信方式必须使用专用的共享信道协议来协调这些主机的数据发送 使用点对点信道的数据链路层 数据链路和帧 链…...

【Linux】Ubuntu 22.04 升级 nodejs 到 v18

Ubuntu 22.04 已经安装的nodejs 版本 nodejs is already the newest version (12.22.9~dfsg-1ubuntu3.3). 删除以前的 nodejs 版本&#xff1a; 1. sudo apt remove nodejs rooterp:~# sudo apt remove nodejs Reading package lists... Done Building dependency tree..…...

当go get获取不到软件包时

当使用go get命令获取软件包时&#xff0c;如果无法成功获取&#xff0c;您可以尝试以下方法来解决问题&#xff1a; 检查网络连接&#xff1a;首先&#xff0c;确保您的计算机能够访问互联网&#xff0c;并且没有任何网络防火墙或代理设置阻止了go get命令的正常运行。 设置代…...

全网最详细解法|同济大学|高等数学|第八版|习题1-5

文章目录 全网最详细解法&#xff5c;同济大学&#xff5c;高等数学&#xff5c;第八版&#xff5c;习题1-5&#xff5c;5.1全网最详细解法&#xff5c;同济大学&#xff5c;高等数学&#xff5c;第八版&#xff5c;习题1-5&#xff5c;5.2 全网最详细解法&#xff5c;同济大学…...

可视化工具:将多种数据格式转化为交互式图形展示的利器

引言 在数据驱动的时代&#xff0c;数据的分析和理解对于决策过程至关重要。然而&#xff0c;不同的数据格式和结构使得数据的解读变得复杂和困难。为了解决这个问题&#xff0c;一种强大的可视化工具应运而生。这个工具具有将多种数据格式&#xff08;包括JSON、YAML、XML、C…...

[嵌入式AI从0开始到入土]14_orangepi_aipro小修补含yolov7多线程案例

[嵌入式AI从0开始到入土]嵌入式AI系列教程 注&#xff1a;等我摸完鱼再把链接补上 可以关注我的B站号工具人呵呵的个人空间&#xff0c;后期会考虑出视频教程&#xff0c;务必催更&#xff0c;以防我变身鸽王。 第1期 昇腾Altas 200 DK上手 第2期 下载昇腾案例并运行 第3期 官…...

机器学习、深度学习、强化学习、迁移学习的关联与区别

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本文主要了解并初步探究机器学习、深度学习、强化学习、迁移学习的关系与区别&#xff0c;通过清晰直观的关系图展现出四种“学习”之间的关系。虽然这四种“学习”方法在理论和应用上存在着一定的区别&#xff0c;但它们之间也…...

苹果为什么需要台积电3nm工艺芯片?

据《经济日报》报道&#xff0c;苹果公司的产品线将迎来重大升级。下一代应用于iPad、MacBook和iPhone的M4和A18处理器预计将会增加内置AI计算核心的数量&#xff0c;从而大幅提高AI运算能力。这一变化将导致对台积电&#xff08;TSMC&#xff09;订单的显著增长。据悉&#xf…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...