手把手教你怎么写顺序表

news2024/11/13 23:25:25

目录

一、顺序表有什么功能?

二、实现顺序表的各个功能

1.前置准备

2.初始化顺序表

3.顺序表扩容

4.打印顺序表

5.增加顺序表成员

5.1尾增

5.2头增

 6.删除顺序表中成员的内容

6.1尾删

6.2头删

 7.查找成员

 8.修改(替换)

9.插入(在目标位置插入成员)

10.定向删除(将目标位置的成员删除)

三、全部代码

1.函数头文件

2.函数实现


一、顺序表有什么功能?

这就像是大纲一样,只要我们明确了要实现的功能,之后就是努力地实现它们就好了,众所周知,顺序表是在计算机内存中以数组的形式保存我们需要的数据。既然数据被保存了,那么我们接下来就是对这些保存好的数据进行对应的操作,增删改查是必须要有的,接着,我们想将顺序表中的内容打印出来,看看到底有没有正确的存储我们需要的数据,我们可以再设计一个打印函数,想对顺序表的内容排序也可以再设计一个排序函数,反正根据自己所需设计,但是增删改查是最基本的,必须要有的。

二、实现顺序表的各个功能

1.前置准备

在实现顺序表的各个功能之前我们得先有点前置准备内容,顺序表的成员类型,顺序表这个结构体的设计,头文件的引用......这些操作笔者推荐都放在一个头文件中进行,这样在调用的时候仅需引用一个头文件即可完成我们需要的功能。

// SeqList.h
//将所需函数和所需头文件的引用放在一个头文件中,那么在使用的时候就只用引用一个头文件
#pragma once//防止头文件被重复引用
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>//可能要用到的头文件
typedef int SlDateType;
//将int typedef成SlDateType这样就可以区分int和顺序表成员
// 虽然它们的类型本质上都是int但是它们的字面含义已经不同
//当然了,可以把int换成别的类型
//这样子设计其实更多的是为了到时顺序表成员类型想更换直接从这换就全换了,不用一个一个换
typedef struct seqlist
{
	SlDateType* a;
	//创建一个指针类型的顺序表成员数据,为什么是指针?
	//这样做是为了到时能够使用malloc和realloc对空间的大小进行开辟与修改
	//相当于柔性数组
	int sz;//已经存放了多少个成员
	int capacity;//容量大小,以后判定空间是否够用可以通过这个来判定
}seqlist;//将结构体名字命名为seqlist,使用时更加方便

2.初始化顺序表

记得在书写代码之前将之前的顺序表头文件引用进来,这样就可以用到顺序表头文件的内容。

//顺序表.c
#include"顺序表.h"
void init_seqlist(seqlist* s1)//通过指针的形式访问,便能够对内容进行修改
{
	s1->capacity = 3;//将容量大小初始化为3,为了更好地测试到时的扩容效果
	s1->sz = 0;//将成员数量初始化为0,代表着此时没有存放成员
	s1->a = (SlDateType*)malloc(sizeof(SlDateType) * s1->capacity);
	//将顺序表的成员数组大小初始化和容量一样的大小
	if (s1->a == NULL)//开辟失败的话直接退出程序
	{
		exit(-1);
	}
}

在顺序表.c中书写完函数的内容后别忘了在顺序表.h中引用它,这样别人才能够只引用一个头文件就能够使用对应函数。

3.顺序表扩容

在存放顺序表成员之前我们应该要注意的一点就是,我们的容量是有限的,那么在触及容量的时候,也就是顺序表已经被装满的时候,我们应该要扩容处理,避免出现装不下内容的情况出现。

void if_enough(seqlist* s1)
{
	if (s1->sz == s1->capacity)
	//当容量和成员个数相当时,显然就已经存满了,需要扩容
	{
		s1->a = realloc(s1->a,sizeof(SlDateType)*s1->capacity*2);
		//将容量扩大到原来容量的两倍
		if (s1->a == NULL)
		{
			perror("if_enough");//错误提示
			return;//中止程序
		}
		s1->capacity *= 2;//扩容成功,容量翻倍
		printf("扩容成功,当前容量为%d\n",s1->capacity);//扩容成功给个提示
	}
}

4.打印顺序表

在增加之前,我们就会意识到这样一个问题,倘若我增加了顺序表成员,但我又该如何分辨出我成功增加了顺序表成员呢,听着是不是很绕?其实就是我们不能够直接的看到顺序表的内容,因此我们可以使用打印的方式将顺序表的内容打印出来。

void print_seqlist(const seqlist* s1)
//将内容打印出来,但内容是不会被改变的,因此用const修饰,避免内容被修改
{
	if (s1->sz == 0)
	{
		printf("顺序表为空,操作失败\n");
		return;
	}
	int i = 0;
	for (i = 0; i < s1->sz; i++)
	{
		printf("%d ", s1->a[i]);//将内容通过循环的方式打印出来
	}
	printf("\n");//打印完所有内容之后最好换行
}

5.增加顺序表成员

5.1尾增

什么是尾增?顾名思义,就是从最后面开始增加,即在顺序表的最后进行成员的添加,注意:在进行增加之前我们需要判断顺序表是否被放满,这个时候就可以使用我们之前创建的if_enough函数来判断是否需要进行扩容处理,如果需要则扩容,不需要则无事发生。

void seqlist_pushback(seqlist*s1,SlDateType x)
{
	if_enough(s1);
	s1->a[s1->sz] = x;//在顺序表的最后插入一个数据x
	s1->sz++;
}

创建一个新的文件,测试一下我们之前写的代码 

//test.c
#include"顺序表.h"
int main()
{
	seqlist s1;
	init_seqlist(&s1);//初始化顺序表
	print_seqlist(&s1);
	//将顺序表内容打印,但此时是空,故不能打印
	seqlist_pushback(&s1, 1);//依次将1,2,3放入顺序表中
	seqlist_pushback(&s1, 2);
	seqlist_pushback(&s1, 3);
	print_seqlist(&s1);//打印顺序表
	seqlist_pushback(&s1, 2);//依次将2,3放入顺序表中
	seqlist_pushback(&s1, 3);
	print_seqlist(&s1);//打印顺序表
}

5.2头增

顾名思义,在顺序表的最开始进行成员的增加,我们不难想象,若是这个顺序表中已经有成员了这么办?难不成直接将这个成员替换成我们的目标?如果这样做就会少一个成员,根据数组的经验,我们只能够通过覆盖的方式先将所有的成员往后挪一个单位,再将最前面的成员替换成我们需要的成员。同样在开始之前我们应该要判断容量是否足够。

这里挪动是核心,同样也是一门学问,笔者在这画副图给大家,大家就懂得如何挪动了

 由图可知,我们要先将最后面的成员往后挪动到下一个空间中,也就是sz对应的空间内容,得是sz-1的空间内容,sz-1的内容得是sz-2的内容,那么就可以通过循环的方式实现,sz-i指向的内容等于sz-i-1指向的内容,i实现一步步的覆盖,这里面比较难想的就是i的范围,由目标分析可知,当sz-i-1=0的时候结束循环,为什么?,因为当sz-i-1=0的时候,sz-i等于1,也就是1对应的目标,等于0对应的目标,完成这一步之后,所有的覆盖就已经结束,根据计算可知,i=sz-1,故i<sz便可以实现所有的覆盖。

void seqlist_pushfront(seqlist* s1, SlDateType x)
{
	if_enough(s1);
	int i = 0;
	for (i=0;i<s1->sz;i++)//通过循环从后往前覆盖
	{
		s1->a[s1->sz - i] = s1->a[s1->sz-i-1];
	}
	s1->a[0] = x;//将首元素替换成x
	s1->sz++;
}

 同样可以测试一下

//test.c
#include"顺序表.h"
int main()
{
	seqlist s1;
	init_seqlist(&s1);//初始化顺序表
	print_seqlist(&s1);
	//将顺序表内容打印,但此时是空,故不能打印
	seqlist_pushback(&s1, 1);//依次将1,2,3放入顺序表中
	seqlist_pushback(&s1, 2);
	seqlist_pushback(&s1, 3);
	print_seqlist(&s1);//打印顺序表
	seqlist_pushfront(&s1,520);//在最前面放入520
	print_seqlist(&s1);//打印顺序表
}

 6.删除顺序表中成员的内容

6.1尾删

这个就很简单了,我们只需要将此时顺序表的成员数量往回拨一位就行。为什么?举个例子,成员中已经有了1,2,3,4,5那么不难得出sz此时是5,指向的是5后面的空间,而当我们把数量往回拨的话,sz就指向了4,那么此时sz就指向了5对应的空间,下次你在再增加内容的时候这个空间就会被自动覆盖掉,同样,打印的话也是根据sz来打印的,会直接略过。唯一需要注意的一点就是,当顺序表的成员为空的时候,也就是没有成员的时候,强行删除的话就会造成越界问题的发生。因为没有成员的时候,sz为0,你对它强行进行删除,那么就会导致sz=-1,下一次再增加元素的时候,就会越界访问。

void seqlist_popback(seqlist* s1)
{
	if (s1->sz == 0)
	{
		printf("顺序表为空,操作失败\n");
		return;
	}
	s1->sz--;
}

6.2头删

头删相对于尾删麻烦一些,我们通过从前往后覆盖的方式将前面的内容覆盖成后面的内容

void seqlist_popfront(seqlist* s1)
{
	if (s1->sz == 0)
	{
		printf("顺序表为空,操作失败\n");
		return;
	}
	int i = 0;
	for (i = 1; i < s1->sz; i++)
	{
		s1->a[i-1] = s1->a[i];//从前往后覆盖
	}
	s1->sz--;
}

同样,我们可以测试一下 

 7.查找成员

目标很简单,就是查找到目标成员然后打印出来,找不到就打印找不到,通过一次遍历就可以搞定

void seqlist_fine(const seqlist* s1,const SlDateType x)
//查找的目标是x,用const修饰是因为只是查找,不用修改
{
	if (s1->sz == 0)
	{
		printf("顺序表为空,操作失败\n");
		return;
	}
	int i = 0;
	for (i = 0;i<s1->sz; i++)
	{
		if (s1->a[i] == x)//相等意味着找到了
		{
			printf("找到%d了,下标为%d\n",x,i);
			return;
		}
	}
	printf("目标不存在\n");
}

同样可以测试一下 

 8.修改(替换)

给对应的下标,和被修改的结果,对目标下标的内容进行修改,要注意的是,我们修改下标的范围只能是在成员组中进行修改,什么意思?就是说,我们不能对还没放成员的下标进行修改

void seqlist_modify(seqlist* s1, int pos, const SlDateType x)
{
	if (pos >= s1->sz)
	//当pos=sz时就已经是对还不是成员的空间进行操作了,更别说后面的了
	{
		printf("当前空间还不是成员的一部分,操作失败\n");
		return;
	}
	s1->a[pos] = x;
}

同样可以测试一下

9.插入(在目标位置插入成员)

需要注意的便是,我们插入的范围是多少,很显然0~sz-1都是可以插入的,这里面已经是有内容的了,那么sz可不可以呢?可以,因为在sz这个位置插入就相当于尾插,还有一点需要注意,那便是插入成员,成员的数量是会增加的,那么也就是说,我们一样要在插入前判断是否需要扩容。

void seqlist_insert(seqlist* s1, int pos, const SlDateType x)
{
	if_enough(s1);
	if (pos > s1->sz)//比sz还大,意味着插入的位置会导致连续性被破坏
	{
		printf("插入位置出错,操作失败\n");
		return;
	}
	int i = 0;
	for (i = 0;i<s1->sz-pos; i++)
	{
		s1->a[s1->sz-i] = s1->a[s1->sz-i-1];//从后向前覆盖
	}
	s1->a[pos] = x;
	s1->sz++;
}

测试一下

10.定向删除(将目标位置的成员删除)

有了之前插入的经验,这个就显得很简单,但要注意的一点则是,它的删除范围只能是0~sz-1,sz不被包括在内,因为sz显而易见还不是成员。

void seqlist_erase(seqlist* s1, int pos)
{
	if (pos >= s1->sz)//等于sz时就已经是在删除未被定义的内容了
	{
		printf("删除位置出错,操作失败\n");
		return;
	}
	int i = 0;
	for (i=0;pos+i+1<s1->sz;i++)
	{
		s1->a[pos+i] = s1->a[pos+i+1];//从前向后覆盖
	}
	s1->sz--;
}

测试一下

 当我们完成了插入和定向删除,其实之前的头插头删,尾插尾删都可以通过这两个函数来替换,这里就不再一一展示,升级版直接放在全部代码里面。

三、全部代码

1.函数头文件

// SeqList.h
//将所需函数和所需头文件的引用放在一个头文件中,那么在使用的时候就只用引用一个头文件
#pragma once//防止头文件被重复引用
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>//可能要用到的头文件
typedef int SlDateType;
//将int typedef成SlDateType这样就可以区分int和顺序表成员
// 虽然它们的类型本质上都是int但是它们的字面含义已经不同
//当然了,可以把int换成别的类型
//这样子设计其实更多的是为了到时顺序表成员类型想更换直接从这换就全换了,不用一个一个换
typedef struct seqlist
{
	SlDateType* a;
	//创建一个指针类型的顺序表成员数据,为什么是指针?
	//这样做是为了到时能够使用malloc和realloc对空间的大小进行开辟与修改
	//相当于柔性数组
	int sz;//已经存放了多少个成员
	int capacity;//容量大小,以后判定空间是否够用可以通过这个来判定
}seqlist;//将结构体名字命名为seqlist,使用时更加方便
//初始化顺序表
void init_seqlist(seqlist*s1);
//打印顺序表
void print_seqlist(const seqlist* s1);
//尾增
void seqlist_pushback(seqlist* s1, SlDateType x);
//头增
void seqlist_pushfront(seqlist* s1, SlDateType x);
//尾删
void seqlist_popback(seqlist* s1);
//头删
void seqlist_popfront(seqlist* s1);
//查找成员
void seqlist_fine(const seqlist* s1,const SlDateType x);
//修改成员
void seqlist_modify(seqlist* s1, int pos, const SlDateType x);
//插入成员
void seqlist_insert(seqlist* s1, int pos, const SlDateType x);
//删除成员
void seqlist_erase(seqlist* s1, int pos);

2.函数实现

//顺序表.c
#include"顺序表.h"
void init_seqlist(seqlist* s1)//通过指针的形式访问,便能够对内容进行修改
{
	s1->capacity = 3;//将容量大小初始化为3,为了更好地测试到时的扩容效果
	s1->sz = 0;//将成员数量初始化为0,代表着此时没有存放成员
	s1->a = (SlDateType*)malloc(sizeof(SlDateType) * s1->capacity);
	//将顺序表的成员数组大小初始化和容量一样的大小
	if (s1->a == NULL)//开辟失败的话直接退出程序
	{
		exit(-1);
	}
}
void if_enough(seqlist* s1)
{
	if (s1->sz == s1->capacity)
	//当容量和成员个数相当时,显然就已经存满了,需要扩容
	{
		s1->a = realloc(s1->a,sizeof(SlDateType)*s1->capacity*2);
		//将容量扩大到原来容量的两倍
		if (s1->a == NULL)
		{
			perror("if_enough");//错误提示
			return;//中止程序
		}
		s1->capacity *= 2;//扩容成功,容量翻倍
		printf("扩容成功,当前容量为%d\n",s1->capacity);//扩容成功给个提示
	}
}
void print_seqlist(const seqlist* s1)
//将内容打印出来,但内容是不会被改变的,因此用const修饰,避免内容被修改
{
	if (s1->sz == 0)
	{
		printf("顺序表为空,操作失败\n");
		return;
	}
	int i = 0;
	for (i = 0; i < s1->sz; i++)
	{
		printf("%d ", s1->a[i]);//将内容通过循环的方式打印出来
	}
	printf("\n");//打印完所有内容之后最好换行
}
void seqlist_pushback(seqlist*s1,SlDateType x)
{
	//if_enough(s1);
	//s1->a[s1->sz] = x;//在顺序表的最后插入一个数据x
	//s1->sz++;
	seqlist_insert(s1,s1->sz,x);
}
void seqlist_pushfront(seqlist* s1, SlDateType x)
{
	//if_enough(s1);
	//int i = 0;
	//for (i=0;i<s1->sz;i++)//通过循环从后往前覆盖
	//{
	//	s1->a[s1->sz - i] = s1->a[s1->sz-i-1];
	//}
	//s1->a[0] = x;//将首元素替换成x
	//s1->sz++;
	seqlist_insert(s1,0, x);
}
void seqlist_popback(seqlist* s1)
{
	/*if (s1->sz == 0)
	{
		printf("顺序表为空,操作失败\n");
		return;
	}
	s1->sz--;*/
	seqlist_erase(s1,s1->sz-1);
}
void seqlist_popfront(seqlist* s1)
{
	//if (s1->sz == 0)
	//{
	//	printf("顺序表为空,操作失败\n");
	//	return;
	//}
	//int i = 0;
	//for (i = 1; i < s1->sz; i++)
	//{
	//	s1->a[i-1] = s1->a[i];//从前往后覆盖
	//}
	//s1->sz--;
	seqlist_erase(s1,0);
}
void seqlist_fine(const seqlist* s1,const SlDateType x)
//查找的目标是x,用const修饰是因为只是查找,不用修改
{
	if (s1->sz == 0)
	{
		printf("顺序表为空,操作失败\n");
		return;
	}
	int i = 0;
	for (i = 0;i<s1->sz; i++)
	{
		if (s1->a[i] == x)//相等意味着找到了
		{
			printf("找到%d了,下标为%d\n",x,i);
			return;
		}
	}
	printf("目标不存在\n");
}
void seqlist_modify(seqlist* s1, int pos, const SlDateType x)
{
	if (pos >= s1->sz)
	//当pos=sz时就已经是对还不是成员的空间进行操作了,更别说后面的了
	{
		printf("当前空间还不是成员的一部分,操作失败\n");
		return;
	}
	s1->a[pos] = x;
}
void seqlist_insert(seqlist* s1, int pos, const SlDateType x)
{
	if_enough(s1);
	if (pos > s1->sz)//比sz还大,意味着插入的位置会导致连续性被破坏
	{
		printf("插入位置出错,操作失败\n");
		return;
	}
	int i = 0;
	for (i = 0;i<s1->sz-pos; i++)
	{
		s1->a[s1->sz-i] = s1->a[s1->sz-i-1];//从后向前覆盖
	}
	s1->a[pos] = x;
	s1->sz++;
}
void seqlist_erase(seqlist* s1, int pos)
{
	if (pos >= s1->sz)//等于sz时就已经是在删除未被定义的内容了
	{
		printf("删除位置出错,操作失败\n");
		return;
	}
	int i = 0;
	for (i=0;pos+i+1<s1->sz;i++)
	{
		s1->a[pos+i] = s1->a[pos+i+1];//从前向后覆盖
	}
	s1->sz--;
}

好了,今天的分享到这里就结束了,感谢各位友友的来访,祝各位友友前程似锦O(∩_∩)O

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kong Ming Qi hdu7321

Problem - 7321 题目大意&#xff1a;在(n2)*(m2)的棋盘上&#xff0c;中间摆满了n*m个棋子&#xff0c;每个棋子可以向上下左右四个方向移动&#xff0c;对于相邻的三格&#xff0c;移动前后分别为 有 有 无->无 无 有&#xff0c;问最后棋盘上最少能剩下几个棋子 1<n…

论文解读|PF-Net:用于 3D 点云补全的点分形网络

原创 | 文 BFT机器人 01 背景 从激光雷达等设备中获取的点云往往有所缺失&#xff08;反光、遮挡等&#xff09;&#xff0c;这给点云的后续处理带来了一定的困难&#xff0c;也凸显出点云补全作为点云预处理方法的重要性。 点云补全&#xff08;Point Cloud Completion&#x…

Drools用户手册翻译——第四章 Drools规则引擎(七)规则执行模式和线程安全

甩锅声明&#xff1a;本人英语一般&#xff0c;翻译只是为了做个笔记&#xff0c;所以有翻译错误的地方&#xff0c;错就错了&#xff0c;如果你想给我纠正&#xff0c;就给我留言&#xff0c;我会改过来&#xff0c;如果懒得理我&#xff0c;就直接划过即可。 drools的规则执…

HighTec 工程属性介绍2

目录 首先需要创建或导入一个工程&#xff0c;如下图&#xff1a; 有两种方式可以进入工程的属性面板&#xff1a; 选中工程&#xff0c;右键点击 Properies . 选中工程&#xff0c;按键 Alt Enter. 进入工程属性面板之后&#xff0c;左侧是书签标记&#xff0c;右侧是该书…

How to choose WIFI7 IPQ9554- WIFI6 IPQ8072? Who has the better performance?

How to choose WIFI7 IPQ9554- WIFI6 IPQ8072? Who has the better performance? The Wi-Fi standard is Wi-Fi 6, also known as 802.11ax. Wi-Fi 6 brings significant speed, capacity and performance improvements over the previous Wi-Fi 5 (802.11ac) standard. It p…

如何做好项目管理?年薪百万项目大佬一直在用这11张图!

日常工作中&#xff0c;我们会遇到各种大大小小的工作项目&#xff0c;如何能让项目保质保量的完成&#xff0c;就需要项目管理。项目管理是什么&#xff1f;一句话解释&#xff1a;在有限的时间内&#xff0c;在约束的范围中&#xff0c;集合有限资源来完成项目目标。 本周小编…

如何安装mmcv?官网解答

pip install -U openmim mim install mmcv

什么是宏变量和宏替换?

在Java中&#xff0c;宏变量和宏替换通常是与C/C预处理器相关的概念&#xff0c;而不是Java本身的特性。在Java中&#xff0c;我们通常不使用预处理器指令(例如宏定义)来进行代码替换。Java使用的编译器并不支持预处理器指令&#xff0c;因此没有宏替换的概念。 然而&#xff0…

移动硬盘文件或目录损坏且无法读取

早上插上硬盘&#xff0c;拔的时候不太规范&#xff0c;再插进去就显示无法读取了 搜了很多方法&#xff0c;很多让使用什么软件进行恢复 还参考了这个方法&#xff0c;但是我的属性打开跟博主的完全不一样 最后&#xff0c;参考移动硬盘“文件或目录损坏&#xff0c;无法读取…

[NOIP2007 普及组] 守望者的逃离

[NOIP2007 普及组] 守望者的逃离 题目背景 恶魔猎手尤迪安野心勃勃&#xff0c;他背叛了暗夜精灵&#xff0c;率领深藏在海底的娜迦族企图叛变。 题目描述 守望者在与尤迪安的交锋中遭遇了围杀&#xff0c;被困在一个荒芜的大岛上。 为了杀死守望者&#xff0c;尤迪安开始…

把一个列表拆成N个子列表的四种方法

编程的方法往往不止一种&#xff0c;比如怎么把一个Python种的列表拆成N个子列表&#xff0c;我们可以很容易找到N种方法&#xff0c;也许这就是编程的魅力所在。 一、列表表达式法 这种方法最为简洁&#xff0c;不过可读性差一些 这个方法中&#xff0c;即使原始列表的数量无…

途乐证券:美联储第11次加息 年内降息预期下降

7月26日&#xff0c;美国联邦储藏委员会主席鲍威尔在华盛顿到会记者会。新华社发 当地时刻7月26日&#xff0c;美国联邦储藏委员会一如预期加息25个基点。商场对美联储未来是否会持续加息尚未彻底构成共识&#xff0c;但对年内美联储将敞开降息周期的预期下降。 抑通胀 美联储…

24考研数据结构-队列2

目录 数据结构之队列&#xff1a;链式存储结构与循环队列链式存储结构链式队列的结构链式队列的操作 循环队列循环队列的结构循环队列的操作 链式队列与循环队列的比较结论3.2.3 队列的链式存储结构3.2.3.1定义3.2.3.2链式队列的基本操作——带头结点3.2.3.3 不带头结点的相关操…

PLC自学是否可行?

plc编程的关键是模拟原操作流程&#xff0c;通过运行程序完成控制过程。所以核心内容就是程序对流程的描述。因此&#xff0c;掌握PLC编程语言和基本功能实现是很有必要的。 PLC语言分为梯形图、语句和功能图。常用梯形图&#xff0c;适合基本逻辑描述&#xff0c;语句表适合数…

计算机网络(1) --- 网络介绍

目录 1.介绍协议 基础知识 协议 协议分层 OSI七层模型 2.TCP/IP五层模型 3.网络传输的基本流程 1.基本知识 协议报头 2.局域网通信的基本流程 3.网络传输流程 局域网分类 跨路由器传输 数据包封装和分用 4.网络中的地址管理 1.IP地址 2.MAC地址 3.区别 1.介绍…

商品分类子类新建,手机云进销存,扫码入库出库盘点开单打印

商品分类子类新建&#xff0c;手机扫码开单打印进销存&#xff0c;商贸批发生产企业仓库条码管理软件系统&#xff0c;超市便利店五金茶叶烟酒鞋帽门店零售手机收银管理软件APP_哔哩哔哩_bilibili商品分类子类新建的操作步骤。, 视频播放量 1、弹幕量 0、点赞数 0、投硬币枚数 …

Java基础---final 关键字

目录 定义&#xff1a; 用途&#xff1a; 使用注意事项&#xff1a; final 变量 final 方法 final 类 小结 定义&#xff1a; Java中&#xff0c;final 表示最终&#xff0c;也可以称为完结器&#xff0c;表示对象是最终形态的&#xff0c;不可改变的意思 用途&#xff…

springboot+mybatis多数据源的事务问题

1.springbootmybatis实现多数据源后&#xff0c;针对单个数据源我们可以使用Transactional(name"xxxTransactionManager") 来指定使用的事务管理器&#xff0c;但是如果被注解的方法需要同时支持两个事务管理器呢&#xff0c;这个时候如果用Transactional注解就不 …

设备数字化平台在制药行业数字化转型的思考与实践

近年来&#xff0c;全球制药行业正面临着数字化转型的浪潮。制药4.0的概念正引领着工业物联网、机器人流程自动化和人工智能等先进技术在制药行业的广泛应用。然而&#xff0c;尽管数字化转型在许多行业已经取得了巨大成功&#xff0c;制药行业仍然面临一些挑战。数据孤岛、人才…

git撤销上一次的commit

一行命令 git reset --soft HEAD^如果在vscode上面&#xff0c;就可以