【数据结构】万字深入浅出讲解顺序表(附原码 | 超详解)

news/2023/6/7 23:14:56

在这里插入图片描述

🚀write in front🚀
📝个人主页:认真写博客的夏目浅石.
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:C语言实现数据结构
💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🖊
✉️如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn

文章目录

  • 前言
  • 一、线性表概念
    • 1.1线性表
  • 二、顺序表实现
    • 2.1概念及结构
    • 2.2 接口的布局
    • 2.3接口的实现
      • SeqList.h的代码
      • SeqList.c 的代码
  • 三、完整代码
  • 总结


前言

在这里插入图片描述
这几天看了数据结构的顺序表这一节,真的收获很大,第一次看没有动手敲代码就是感觉学了和没学一样,今天也是从新又看了一遍,并且边学边敲代码,终于算是非常理解顺序表这个东西了,今天就把我所学到的知识给大家分享一下。


提示:以下是本篇文章正文内容,下面案例可供参考

一、线性表概念

1.1线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。

在这里插入图片描述

二、顺序表实现

2.1概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存
储。在数组上完成数据的增删查改。

顺序表一般可以分为:

  • 静态顺序表:使用定长数组存储。
  • 动态顺序表:使用动态开辟的数组存储.

以下是静态顺序表:

#pragma once//防止被重复的包含 #define N 100
typedef int SQDataType;typedef struct SeqList
{SQDataType a[N];SQDataType size; //有效数据 
}SL;
//增删查改等接口函数 //对于结构体的定义typedef struct SeqList SL;//静态顺序表
//问题:给少了不够用,给多了用不完浪费,不能灵活控制

由于静态顺序表无法伸缩变换数组,所以今天着重讲解动态的顺序表

动态顺序表的实现:

//#pragma once 
//#define N 10 对于动态线性表这个就没有用了 
typedef int SQDataType;typedef struct SeqList
{SQDataType* a;int size;	  //有效数据的个数 int capacity; //容量 
}SL;

2.2 接口的布局

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大
了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表根据需要动态
的分配空间大小,所以下面我们实现动态顺序表。

我们需要的工程文件

  • SeqList.h:用于存放函数声明、包含头文件、定义宏等等。
  • test.c:用于写程序整体执行逻辑等。
  • SeqList.c:用于写函数定义,写函数实现等。

2.3接口的实现

SeqList.h的代码

#include<string.h>
#include<stdio.h>//printf
#include<stdlib.h>//realloc 
#include<assert.h>//断言 typedef int SQDataType; //方便修改数据 typedef struct SeqList //重命名方便书写 
{SQDataType* a;int size;	  //有效数据的个数 int capacity; //容量 
}SL;//初始化与销毁:
void SeqListInit(SL* ps);//初始化顺序表 
void SeqListCheckCapcity(SL* ps)//创建新空间---扩容
void SeqListDestory(SL* ps)//销毁空间 //顺序表的插入操作---头插,尾插,任意插
void SeqListPushBack(SL* ps,SQDataType x);//顺序表尾插 o(1) 
void SeqListPushFront(SL* ps,SQDataType x);//顺序表头插  o(n)
void SeqListInsert(SL* ps,int pos,SQDataType x) //在顺序表指定下标位置插入数据 //顺序表的删除操作---头删,尾删,任意删
void SeqListPopBack(SL* ps);//顺序表尾删 o(1)
void SeqListPopfront(SL* ps);//顺序表头删 o(n)
void SeqListErase(SL* ps,int pos) //顺序表任意下标删除 //顺序表的查找、打印、寻找
int SeqListFind(SL* ps,SQDataType x) //顺序表查找下标 
int  SeqListModity(SL* ps,int pos,SQDataType x)//修改指定下标位置的数据 
void SeqListPrint(SL* ps)//打印顺序表元素 

SeqList.c 的代码

这里就是实现上述的函数的代码啦~

  • 初始化顺序表
void SeqListInit(SL* ps)
{aseert(ps)//断言 //初始化ps->a=NULL;//设置为空 ps->size=0;//设置为0 ps->capacity=0;//设置为0 
}
  • 检查顺序表容量和扩容
    如果顺序表空间足够,那么不需要扩容,通过相关操作插入数据,如果空间不足或者根本没有空间,那么就得扩容。

当顺序表没有空间时,我们开辟四个空间(至少为1个空间);当顺序表空间不足,我们将当前空间扩大为两倍

void SeqListCheckCapcity(SL* ps)
{assert(ps!= NULL);  //断言if(ps->size==ps->capacity){int newcapacity=ps->capacity==0?4:ps->capacity*2;//如果是0就改为4,不是0就扩大二倍 SQDataType* tmp=(SQDataType*)realloc(ps->a,newcapacity*sizeof(SQDataType));if(tmp==NULL){printf("realloc fail\n");//扩容失败 exit(-1);}else //扩容成功 {ps->a=tmp;//新的数组对吧 ps->capacity =newcapacity;//有效的容量 }}
}
  • 销毁顺序表
void SeqListDestory(SL* ps)//销毁 
{assert(ps != NULL);  //断言free(ps->a);//释放动态开辟的空间ps->a=NULL;//置空ps->capacity=0;//数据个数置0ps->size=0;//空间容量大小置0
}
  • 顺序表尾插
void SeqListPushBack(SL* ps,SQDataType x)//尾插
{//满了就要扩容 
//	if(ps->size==ps->capacity)
//	{
//		int newcapacity=ps->capacity==0?4:ps->capacity*2;
//		SQDataType* tmp=(SQDataType*)realloc(ps->a,newcapacity*2*sizeof(SQDataType));
//		if(tmp==NULL)
//		{
//			printf("realloc fail\n");
//			exit(-1);
//		}
//		else 
//		{
//			ps->a=tmp;//新的数组对吧 
//			ps->capacity = newcapacity;//有效的容量 
//		}
//	}	SeqListCheckCapcity(ps);//扩容函数 ps->a[ps->size]=x;//设置为要改的数x ps->size++;//让数组长度增加 
}

测试:

void TestSeqList1()
{SL s1;SeqListInit(&s1); //初始化顺序表SeqListPushBack(&s1,1);SeqListPushBack(&s1,2);SeqListPushBack(&s1,3);SeqListPushBack(&s1,4);SeqListPushBack(&s1,5);SeqListPushBack(&s1,6);SeqListPushBack(&s1,7);SeqListPushBack(&s1,8);SeqListPushBack(&s1,9);SeqListPushBack(&s1,10);SeqListPushBack(&s1,11);SeqListPrint(&s1);//打印顺序表:下面实现//销毁顺序表:SeqListDestory(&s1);
}
int main()
{TestSeqList1();//TestSeqList2();return 0;
}

在这里插入图片描述

  • 顺序表尾删
    每次都在最后一个元素之后插入新的元素
void SeqListPopBack(SL* ps)//尾删 
{assert(ps->size>0);//断言 //ps->a[ps->size-1]=0;ps->size--;//数组减少 
}
void TestSeqList2()
{SL s1;SeqListInit(&s1);SeqListPushFront(&s1,1);SeqListPushFront(&s1,2);SeqListPushFront(&s1,3);SeqListPushFront(&s1,4);SeqListPushFront(&s1,5);SeqListPushFront(&s1,6);SeqListPopBack(&s1);SeqListPopBack(&s1);SeqListPopfront(&s1);SeqListPrint(&s1);
}int main()
{//TestSeqList1();TestSeqList2();return 0;
}

在这里插入图片描述

  • 顺序表头插
    每次都在头结点之后插入新元素,头插法较为重要,当遇到链表的逆置操作时,可以使用头插法实现
void SeqListPushFront(SL* ps,SQDataType x)//头插 
{//1.初始条件//2.结束条件//3.迭代过程 //还是要考虑增容的情况SeqListCheckCapcity(ps);//扩容 int end=ps->size-1;//找到end指针 while(end>=0) //循环右移 {ps->a[end+1]=ps->a[end];--end;}ps->a[0]=x;//插入 ps->size++;//数组加大 
}

在这里插入图片描述
实现:

void TestSeqList2()
{SL s1;SeqListInit(&s1);SeqListPushFront(&s1,1);SeqListPushFront(&s1,2);SeqListPushFront(&s1,3);SeqListPushFront(&s1,4);SeqListPushFront(&s1,5);SeqListPushFront(&s1,6);SeqListPopBack(&s1);SeqListPopBack(&s1);SeqListPopfront(&s1);SeqListPrint(&s1);
}int main()
{//TestSeqList1();TestSeqList2();return 0;
}

在这里插入图片描述

  • 顺序表头删
void SeqListPopfront(SL* ps)//头删
{assert(ps->size>0);int start=1;while(start<ps->size){ps->a[start-1]=ps->a[start];++start;}ps->size--;
}

在这里插入图片描述

  • 打印顺序表
void SeqListPrint(SL* ps)
{for(int i=0;i<ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}
  • 顺序表指定下标位置插入数据

插入操作,在表L中的第i个位置上插入指定元素

想要在第i个位置上插入元素,那么就要找到第i − 1 个结点,然后将新结点插入其后面

void SeqListInsert(SL* ps,int pos,SQDataType x) //任意插入 
{assert(pos<ps->size);SeqListCheckCapcity(ps);int end=ps->size-1;while(end>=pos){ps->a[end+1]=ps->a[end];--end;}ps->a[pos]=x;ps->size++;
}
  • 顺序表任意下标删除

但是,使用这个算法有个问题,如果p是最后一个结点,那么当程序执行到p->data = p->next->data这一句时,会出现空指针的错误,所以只能从表头开始依次寻找p的前驱

void SeqListErase(SL* ps,int pos) //任意删除 
{assert(pos<ps->size); int start=pos+1;while(start<ps->size){ps->a[start-1]=ps->a[start];++start;}ps->size--;
}
  • 顺序表查找下标
    按位查找操作。获取表L中第i个位置的元素的值
int SeqListFind(SL* ps,SQDataType x) //查找 
{for(int i=0;i<ps->size;++i){if(ps->a[i] == x){return i;}}return -1;
}
  • 改指定下标位置的数据
int  SeqListModity(SL* ps,int pos,SQDataType x)//修改位置的值 
{assert(pos<ps->size);ps->a[pos]=x;
}

三、完整代码

SeqList.h

#include<string.h>
#include<stdio.h>//printf
#include<stdlib.h>//realloc 
#include<assert.h>//断言 typedef int SQDataType; //方便修改数据 typedef struct SeqList //重命名方便书写 
{SQDataType* a;int size;	  //有效数据的个数 int capacity; //容量 
}SL;void SeqListInit(SL* ps);//初始化顺序表 
void SeqListCheckCapcity(SL* ps)//创建新空间---扩容
void SeqListDestory(SL* ps)//销毁空间 void SeqListPushBack(SL* ps,SQDataType x);//顺序表尾插 o(1) 
void SeqListPushFront(SL* ps,SQDataType x);//顺序表头插  o(n)
void SeqListInsert(SL* ps,int pos,SQDataType x) //在顺序表指定下标位置插入数据 void SeqListPopBack(SL* ps);//顺序表尾删 o(1)
void SeqListPopfront(SL* ps);//顺序表头删 o(n)
void SeqListErase(SL* ps,int pos) //顺序表任意下标删除 int SeqListFind(SL* ps,SQDataType x) //顺序表查找下标 
int  SeqListModity(SL* ps,int pos,SQDataType x)//修改指定下标位置的数据 
void SeqListPrint(SL* ps)//打印顺序表元素 

SeqList.c:


//void SeqListInit(SL* ps);
//{
//	//初始化
//	memset(s1.a,0,sizeof(SQDataType)*N);
//	s1.size=0;
//}
//
//void SeqListPushBack(SL* ps,SQDataType x);//尾插
//{
//	if(ps->size>=N)
//	{
//		printf("SeqList is Full\n");
//		return;
//	}
//	
//	ps->a[ps->size]=x;
//	ps->size++;
//}
//以上就是静态 
//------------------------------------------------
//下面实现动态void SeqListInit(SL* ps);
{//初始化ps->a=NULL;ps->size=0;ps->capacity=0;//开始如果是一个0的话,那么扩容就会失败 
}void SeqListPrint(SL* ps)
{for(int i=0;i<ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}void SeqListPushBack(SL* ps,SQDataType x);//尾插
{//满了就要扩容 
//	if(ps->size==ps->capacity)
//	{
//		int newcapacity=ps->capacity==0?4:ps->capacity*2;
		SQDataType* tmp=(SQDataType*)realloc(ps->a,ps->capacity*2*sizeof(SQDataType));
//		SQDataType* tmp=(SQDataType*)realloc(ps->a,ps->newcapacity*2*sizeof(SQDataType));
//		if(tmp==NULL)
//		{
//			printf("realloc fail\n");
//			exit(-1);
//		}
//		else 
//		{
//			ps->a=tmp;//新的数组对吧 
//			ps->capacity =newcapacity;//有效的容量 
//		}
//	}	SeqListCheckCapcity(&ps);ps->a[ps->size]=x;ps->size++;
}void SeqListDestory(SL* ps)//销毁 
{free(ps->a);ps->a=NULL;ps->capacity=0;ps->size=0;
}void SeqListCheckCapcity(SL* ps)
{if(ps->size==ps->capacity){int newcapacity=ps->capacity==0?4:ps->capacity*2;SQDataType* tmp=(SQDataType*)realloc(ps->a,newcapacity*sizeof(SQDataType));if(tmo==NULL){printf("realloc fail\n");exit(-1);}else {ps->a=tmp;//新的数组对吧 ps->capacity =newcapacity;//有效的容量 }}
}void SeqListPushFront(SL* ps,SQDataType x);//头插 
{//1.初始条件//2.结束条件//3.迭代过程 //还是要考虑增容的情况SeqListCheckCapcity(&ps);int end=ps->size-1;while(end>=0){ps->a[end+1]=ps->a[end];--end;}ps->a[0]=x;ps->size++;
}void SeqListPopBack(SL* ps)//尾删 
{assert(ps->size>0)//ps->a[ps->size-1]=0;ps->size--;
}void SeqListPopfront(SL* ps)//头删
{assert(ps->size>0)int start=1;while(start<ps->size){ps->a[start-1]=ps->a[start];++start;}ps->size--;
}void SeqListInsert(SL* ps,int pos,SQDataType x) //任意插入 
{assert(pos<ps->size);SeqListCheckCapcity(&ps);int end=ps->size-1;while(end>=pos){ps->a[end+1]=ps->a[end];--end;}ps->a[pos]=x;ps->size++;
}void SeqListErase(SL* ps,int pos) //任意删除 
{assert(pos<ps->size)int start=pos+1;while(start<ps->size){ps->a[start-1]=ps->a[start];++start;}ps->size--;
}int SeqListFind(SL* ps,SQDataType x) //查找 
{for(int i=0;i<ps->size;++i){if(ps->a[i] == x){return i;}}return -1;
}int  SeqListModity(SL* ps,int pos,SQDataType x)//修改位置的值 
{assert(pos<ps->size);ps->a[pos]=x;
}

test.c

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//#pragma once 
//#define N 10 对于动态线性表这个就没有用了 
typedef int SQDataType;typedef struct SeqList
{SQDataType* a;int size;	  //有效数据的个数 int capacity; //容量 
}SL;void SeqListInit(SL* ps)
{////初始化ps->a=NULL;//设置为空 ps->size=0;//设置为0 ps->capacity=0;//设置为0 
}void SeqListCheckCapcity(SL* ps)
{assert(ps!= NULL);  //断言if(ps->size==ps->capacity){int newcapacity=ps->capacity==0?4:ps->capacity*2;//如果是0就改为4,不是0就扩大二倍 SQDataType* tmp=(SQDataType*)realloc(ps->a,newcapacity*sizeof(SQDataType));if(tmp==NULL){printf("realloc fail\n");//扩容失败 exit(-1);}else //扩容成功 {ps->a=tmp;//新的数组对吧 ps->capacity =newcapacity;//有效的容量 }}
}void SeqListPushBack(SL* ps,SQDataType x)//尾插
{//满了就要扩容 
//	if(ps->size==ps->capacity)
//	{
//		int newcapacity=ps->capacity==0?4:ps->capacity*2;
//		SQDataType* tmp=(SQDataType*)realloc(ps->a,newcapacity*2*sizeof(SQDataType));
//		if(tmp==NULL)
//		{
//			printf("realloc fail\n");
//			exit(-1);
//		}
//		else 
//		{
//			ps->a=tmp;//新的数组对吧 
//			ps->capacity = newcapacity;//有效的容量 
//		}
//	}	SeqListCheckCapcity(ps);//扩容函数 ps->a[ps->size]=x;//设置为要改的数x ps->size++;//让数组长度增加 
}void SeqListPushFront(SL* ps,SQDataType x)//头插 
{//1.初始条件//2.结束条件//3.迭代过程 //还是要考虑增容的情况SeqListCheckCapcity(ps);//扩容 int end=ps->size-1;//找到end指针 while(end>=0) //循环右移 {ps->a[end+1]=ps->a[end];--end;}ps->a[0]=x;//插入 ps->size++;//数组加大 
}void SeqListPopBack(SL* ps)//尾删 
{assert(ps->size>0);//断言 //ps->a[ps->size-1]=0;ps->size--;//数组减少 
}void SeqListPopfront(SL* ps)//头删
{assert(ps->size>0);int start=1;while(start<ps->size){ps->a[start-1]=ps->a[start];++start;}ps->size--;
}void SeqListInsert(SL* ps,int pos,SQDataType x) //任意插入 
{assert(pos<ps->size);SeqListCheckCapcity(ps);int end=ps->size-1;while(end>=pos){ps->a[end+1]=ps->a[end];--end;}ps->a[pos]=x;ps->size++;
}void SeqListErase(SL* ps,int pos) //任意删除 
{assert(pos<ps->size); int start=pos+1;while(start<ps->size){ps->a[start-1]=ps->a[start];++start;}ps->size--;
}int SeqListFind(SL* ps,SQDataType x) //查找 
{for(int i=0;i<ps->size;++i){if(ps->a[i] == x){return i;}}return -1;
}int  SeqListModity(SL* ps,int pos,SQDataType x)//修改位置的值 
{assert(pos<ps->size);ps->a[pos]=x;
}void SeqListPrint(SL* ps)
{for(int i=0;i<ps->size;++i){printf("%d ",ps->a[i]);}printf("\n");
}void TestSeqList1()
{SL s1;SeqListInit(&s1);SeqListPushBack(&s1,1);SeqListPushBack(&s1,2);SeqListPushBack(&s1,3);SeqListPushBack(&s1,4);SeqListPushBack(&s1,5);SeqListPushBack(&s1,6);SeqListPushBack(&s1,7);SeqListPushBack(&s1,8);SeqListPushBack(&s1,9);SeqListPushBack(&s1,10);SeqListPushBack(&s1,11);SeqListPrint(&s1);
}void TestSeqList2()
{SL s1;SeqListInit(&s1);SeqListPushFront(&s1,1);SeqListPushFront(&s1,2);SeqListPushFront(&s1,3);SeqListPushFront(&s1,4);SeqListPushFront(&s1,5);SeqListPushFront(&s1,6);SeqListPopBack(&s1);SeqListPopBack(&s1);SeqListPopfront(&s1);SeqListPrint(&s1);
}int main()
{//TestSeqList1();TestSeqList2();return 0;
}

总结

  今天学习了线性表的知识,初次写数据结构的知识,给我的感觉就是,学三遍不如手敲代码一遍来的实在,所以数据结构的学习我将多画图,多敲代码来学习,希望大家吸取经验和我一起学习数据结构,为后面打比赛刷题打下坚实基础。

  我是夏目浅石,希望和你一起学习进步,刷题无数!!!希望各位大佬能一键三连支持一下博主,hhhh~我们下期见喽
在这里插入图片描述
如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn

原创不易,还希望各位大佬支持一下\textcolor{blue}{原创不易,还希望各位大佬支持一下}原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力!\textcolor{9c81c1}{点赞,你的认可是我创作的动力!}点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!\textcolor{ed7976}{收藏,你的青睐是我努力的方向!}收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富!\textcolor{98c091}{评论,你的意见是我进步的财富!}评论,你的意见是我进步的财富!

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

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

html背景怎么改成护眼模式,Win10窗口的白色背景颜色怎么设置成护眼色?

Win10发布了&#xff0c;相信好多小伙伴都已安装并畅快地使用了&#xff0c;可问题来了&#xff0c;Win10的窗口背景颜色也太惨白了&#xff0c;想改还不能轻易改掉&#xff0c;尤其是使用word时&#xff0c;那满屏的白可真的能亮瞎眼啊......好在经过摸索尝试&#xff0c;就目…

让你的电脑全面开启深色模式

文章目录全面深色模式记录我设置深色背景的经历1.全局护眼黄色2.系统的全面黑色模式3. 浏览器的深色化4.Word和PDF的深色化全面深色模式 记录我设置深色背景的经历 作为一名程序员&#xff0c;每天要和显示器屏幕打很长时间交道&#xff1b;但windows的系统背景色和应用背景色…

keil5配色修改(详细)护眼清新

目录一、效果对比图二、windows护眼颜色设置2.1开启步骤2.2关闭步骤三、keli5颜色设置四、展示与对比一、效果对比图 先看一下效果对比图   这是我没设置时的keil5默认的编程界面&#xff0c;字体还是工整好看的&#xff0c;但是界面比较亮白&#xff0c;不适合长时间在办公室…

win10 - 淡绿色护眼背景(注册表)

win10 - 淡绿色护眼背景(注册表)注册表win10一言&#xff1a;提笔思念&#xff0c;落笔无言。炉中的香&#xff0c;让它消散吧&#xff0c;桌上的茶&#xff0c;随它渐凉。知道你还在张望&#xff0c;就足够温暖。效果图 记事本背景 word 文档背景 还有其他的一些编辑界面也会改…

WIN10系统如何设置系统的护眼色

2019独角兽企业重金招聘Python工程师标准>>> 小编的眼神不是很好&#xff0c;所以喜欢把电脑的各种文档的背景色设置成护眼色&#xff08;就是在视觉效果看起来非常舒适的那种淡绿色&#xff09; 工具/原料 装有win10系统的电脑 能够正常输入的键盘鼠标 方法/步骤 …

如何将win7系统的电脑屏幕改成护眼的豆沙绿

长期盯着电脑看是否会有眼睛酸痛的感觉呢&#xff0c;那么来设计一款豆沙绿放松一下眼睛吧。 首先新建一个word文档 将新建的文档最小化&#xff0c;右击桌面选择个性化设置&#xff0c;出现该页面之后选择下面的窗口颜然后点击窗口颜色对话框最下面的高级外观设置 。 打…

File Browser 安装及使用(ubuntu16.04)

参考链接&#xff1a;https://www.mivm.cn/filebrowser/ 当然英文好的大佬也可以直接参考官方文档&#xff1a;https://docs.filebrowser.xyz/installation 建议直接参考我下面的内容进行安装和配置&#xff0c;我对上面链接的博文存在错误的地方做了适当修正。 安装及配置 …

【.Net实用方法总结】 整理并总结System.IO中File类及其方法介绍

&#x1f40b;作者简介&#xff1a;博主是一位.Net开发者&#xff0c;同时也是RPA和低代码平台的践行者。 &#x1f42c;个人主页&#xff1a;会敲键盘的肘子 &#x1f430;系列专栏&#xff1a;.Net实用方法总结 &#x1f980;专栏简介&#xff1a;博主针对.Net开发和C站问答过…