数据结构之栈,队列,树

news2024/12/26 22:37:04

目录

一.栈

1.栈的概念及结构

2.栈的实现

3.实现讲解

1.初始化栈

2.销毁栈

3.压栈

4.出栈

5.返回栈顶元素

6.返回栈内元素个数

7.判断栈内是否为空

二.队列

1.队列的概念及结构

2.队列的实现

3.实现讲解

1.初始化队列

2.销毁队列

3.单个成员入队列

4.单个成员出队列

5.判断队列是否为空

6.返回队列内元素个数

7.返回队列首个元素

8.返回队列尾部元素

三.树

1.树的概念概念及结构

2.树的相关概念

3.树的实现

4.实现讲解

1.初始化树

2.销毁树

3.单个成员插入树

4.单个成员移除树

5.判断树是否为空

6.返回树中元素个数

7.返回树的顶部元素


———————————————————本文开始——————————————————

一.栈

1.栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。
栈中的数据元素遵守后进先出 LIFO(Last In First Out) 的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶
出栈:栈的删除操作叫做出栈。出数据也在栈顶
下面是栈的概念图:

2.栈的实现

对于栈的实现我们可以使用数组或者是链表来完成,这里我们用数组来模拟实现一个栈:

3.实现讲解

对于栈,我们可以采用顺序表的形式来编写,首先是来对Stack结构体的定义,我们定义容量,栈顶数,以及数据指针

typedef int StackDataType;
typedef struct Stack
{
	StackDataType* data;
	int capacity;
	int top;
}Stack;

其次,我们想让栈具有以下几个功能,分别是:

1.初始化栈

2.销毁栈

3.压栈

4.出栈

5.返回栈顶元素

6.返回栈内元素个数

7.判断栈是否为空

下面我们分批次来完成这些函数功能:

1.初始化栈

我们先对栈来申请四个数据类型的空间,这里我们可以使用malloc函数,判断一下是否开辟成功,然后我们把开辟出的空间的地址赋值给栈内的data,将栈内的容量capacity赋值为开辟的数量4,将栈内的栈顶数置为0

void StackInit(Stack* q)
{
	assert(q);
	StackDataType* tmp = (StackDataType*)malloc(sizeof(StackDataType) * 4);
	if (tmp == NULL)
	{
		perror("malloc failed");
		return;
	}
	q->data = tmp;
	q->capacity = 4;
	q->top = 0;
}

2.销毁栈

比较简单!我们直接释放掉栈内的data指针所指向的空间,将data置为空即可:

void StackDestroy(Stack* q)
{
	free(q->data);
	q->data = NULL;
}

3.压栈

将数据压入栈内,这里我们首先先来对栈内的容量和栈顶数做一个判断:

如果栈顶数等于栈的容量数,那么就说明此时栈已经满了,我们需要对栈进行扩容,

这里我们使用realloc函数,对栈内的data指针重新调整一块空间,这里我们同样简单判断一下空间是否开辟成功,并将栈内的容量数+4,代表我们扩容成功,

随后我们将要进行压栈的数据,放入data中,这里top就发挥作用了,可以让我们直接访问栈顶对应的空间,赋值即可,随后把top++代表放入数据成功:

void StackPush(Stack* q, StackDataType x)
{
	if (q->capacity == q->top)
	{
		StackDataType* tmp = (StackDataType*)realloc(q->data, sizeof(StackDataType) * (q->capacity + 4));
		if (tmp == NULL)
		{
			perror("realloc failed");
			return;
		}
		printf("extend successfully");
		q->data = tmp;
		q->capacity += 4;
	}
	q->data[q->top++] = x;
}

4.出栈

这里我们要使用另一个函数,判断栈内是否为空,如果为空,那么就没有数据可供pop出去了,我们结束这个函数,在自己撰写时,请记住提前声明函数哦,这样之后我们直接对栈内的top--即可:

void StackPop(Stack* q)
{
	assert(q);
	assert(!StackEmpty(q));
	q->top--;
}

5.返回栈顶元素

操作之前先来判断一下栈内是否为空,如果为空那么取栈顶数top-1就是错误访问数组了,

如果不为空,我们才返回data中的第top-1的元素:

STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->a[ps->top-1];
}

6.返回栈内元素个数

这里不需要进别的操作,直接返回栈顶数top即可:

int StackSize(Stack* ps)
{
	return ps->top;
}

7.判断栈内是否为空

返回一个判断栈顶数top是否为0的表达式即可:

bool StackEmpty(Stack* ps)
{
	return ps->top == 0;
}

二.队列

1.队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 的性质
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头

2.队列的实现

如果要实现一个队列,如果我们模仿栈使用一个顺序表,那么出队列的时候就很麻烦了!,因此我们在这里使用更为方便的链表实现队列的功能:

先来定义队列中每个成员节点的内容以及队列结构体中的首尾指针,哦对了!千万别忘记了添加一个int size成员,这关联到一个队列的重要功能!:

typedef int QDatatype;

typedef struct  QueueNode
{
	struct QueueNode* next;
	QDatatype data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

一个完整的队列应该具备以下几个功能:

1.初始化队列

2.销毁队列

3.单个成员入队列

4.单个成员出队列

5.判断队列是否为空

6.返回队列内元素个数

7.返回队列首个元素

8.返回队列尾部元素

3.实现讲解

1.初始化队列

这里我们传入一个Queue类型的指针,默认已经创建好了一个Queue结构体,我们只需使用指针把Queue内的tail和head头尾指针置为空,代表元素个数的size置为0,就完成了队列的初始化:

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

2.销毁队列

销毁队列难度不大,我们定义一个QNode*类型的指针cur,让cur从头指针head开始遍历整个队列,再定义另一个指针prev用来备份cur,判断条件就设置为cur!=NULL,然后让cur依次指向下一个节点,每次cur指向下一个节点之前都赋值给prev,再释放prev指向的空间,然后我们再把Queue结构体中的head,tail头尾指针置为空,size赋值为0即可:

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	QNode* prev = NULL;
	while (cur)
	{
		prev = cur;
		cur = cur->next;
		free(prev);
	}
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

3.单个成员入队列

入队列,PushQueue,这里我们传入Queue*指针,以及要入队列的数据x,我们使用malloc先开辟一块QNode的空间来存放我们的数据,完成一个节点的创建,将newnode的next置为NULL,data赋值x,其次,将这一节点连接到队列当中去,这里其实类似于链表中的尾插,最后,别忘了让Queue中的size自加!

void QueuePush(Queue* pq, QDatatype x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc failed");
		return;
	}
	newnode->next = NULL;
	newnode->data = x;
	if (pq->tail == NULL)
	{
		pq->head = newnode;
		pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

4.单个成员出队列

单个成员出队列,我们只需将head指针备份一下,将head重新赋值为下一个节点的地址,再释放备份的地址的空间,完成了出队列的功能,这里需要注意的是,当队列中只有一个成员时,出队列后head指向的是空,同时我们还需将tail改为空,否则在访问队列尾部成员的时候会对空指针进行非法解引用操作,并且要将size自减一个,代码如下:

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	QNode* del = pq->head;
	pq->head = pq->head->next;
	free(del);
	del = NULL;
	if (pq->head == NULL)
	{
		pq->tail = NULL;
	}
	pq->size--;
}

5.判断队列是否为空

这里比较简单,我们直接返回判断size是否为0的表达式即可,值得一提的是,在前面出队列的时候,我们可以先用这一函数来判断队列是否为空,代替断言:

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

6.返回队列内元素个数

这里我们返回size就可以了,同样比较简单:

int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

7.返回队列首个元素

请注意,这里如果直接对head指针进行解引用,那么head可能为空,引发非法解引用的错误,因此,我们需要用到上面的函数,来判断队列是否为空,其次再返回头部成员:

QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}

8.返回队列尾部元素

同样的道理,这里如果直接对tail指针进行解引用,那么tail可能为空,引发非法解引用的错误,因此,我们需要用到上面的函数,来判断队列是否为空,其次再返回尾部成员:

QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}

三.树

1.树的概念概念及结构

树型结构是一类重要的非线性数据结构。其中以树和二叉树最为常用,直观看来,树是以分支关系定义的层次结构。把它叫做“树”是因为它常看起来像一棵倒挂的树,也就是说它常是根朝上,而叶朝下的。

2.树的相关概念

节点的度 一个节点含有的子树的个数称为该节点的度; 如上图:A的为6
叶节点或终端节点 度为0的节点称为叶节点; 如上图:B、C、H、I...等节点为叶节点
非终端节点或分支节点:度不为0的节点; 如上图:D、E、F、G...等节点为分支节点
双亲节点或父节点 若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点
孩子节点或子节点 一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点
兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点
树的度:一棵树中, 最大的节点的度称为树的度; 如上图:树的度为6
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次; 如上图:树的高度为4
堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
子孙 以某节点为根的子树中任一节点都称为该节点的子孙 。如上图:所有节点都是A的子孙
森林:由m(m>0)棵互不相交的树的集合称为森林;

3.树的实现

树的实现可以采用链表实现,也可以采用顺序表也就是数组实现,这里我们只介绍数组实现树的方法,首先是对树这个结构体的定义问题,跟我们的顺序表相同,我们定义储存数据类型的指针,用来记录数据存放个数的size,以及后面用来放入数据判断是否需要扩容的capacity

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

一个完整的树应该具备以下几个功能:

1.初始化树

2.销毁树

3.单个成员插入树

4.单个成员移除树

5.判断树是否为空

6.返回树中元素个数

7.返回树的顶部元素

4.实现讲解

1.初始化树

初始化一个树,我们只需先使用malloc开辟一个初始设定值的空间来存放数据,并且,将结构体内部的capacity设定为初始值,size置为0即可,下面是代码实现:

void HeapInit(HP* php)
{
	assert(php);
	php->a = (HPDataType*)malloc(sizeof(HPDataType) * 4);
	if (php->a == NULL)
	{
		perror("malloc failed");
		return;
	}
	php->size = 0;
	php->capacity = 4;
}

2.销毁树

比较简单,我们直接释放掉结构体内存放数据的指针a所指向空间即可,如果有必要的话可以将a置为NULL,防止野指针的产生,然后我们将capacity和size都置为0即可:

void HeapDestroy1(HP* php)//这里函数名后面加1是因为可能会与系统的函数冲突!
{
	free(php->a);
	php->a = NULL;
	free(php);	
	php = NULL;
}

3.单个成员插入树

这里首先要来判断树的容量是否足够大,也就是树中的capacity是否与size相等,如果相等那么就需要扩容,这里我们使用realloc重新申请一块capacity+增长值的空间,再重新赋给a,

同时capacity加上增长的值就完成了扩容,我们将要插入的数据放在最后,size++,到这里还没有结束,这也是树不同于前面链表与顺序表的地方,我们还需要对树进行调整

这里我选择的是建大堆,那么就是说父亲节点比孩子节点要大,我们插入一个AdjustUp调整树函数:

void HeapPush(HP* php, HPDataType x)
{
	if (php->capacity == php->size)
	{
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * (php->capacity + 4));
		if (tmp == NULL)
		{
			perror("realloc failed");
			return;
		}
		php->a = tmp;
		php->capacity += 4;
	}
	php->a[php->size++] = x;
	AdjustUp(php->a, php->size - 1);
}

下面是AdjustUp的实现:

对于这个函数,我们传入孩子节点以及要调整的数组的地址,定义父亲节点

这里需要用到一条规律:父亲节点=(孩子节点-1)/2;具体的推导过程可以参考别的讲解文章,不在此做过多介绍,将孩子节点的值与父亲节点比较,

如果前者大于后者,那么就进行交换,将父亲节点作为孩子节点继续判断,直到前者小于等于后者,就结束比较,外层我们使用一个while循环,条件设置为child>0,

为什么不是parent<0呢?经过计算发现,parent不可能小于0,最小就是0,因此最佳的解决方案是判断孩子节点的下坐标:

void swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		if (a[child] > a[parent])
		{
			swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

4.单个成员移除树

首先判断树是否为空,如果不为空,就将数组的第一个值与最后一个值进行交换,因为这里Pop的是树的顶部元素,大堆顶部元素是最大的,我们进行交换后将size--,这样就访问间接删除了顶部元素,然后这里我们还需要向下建堆,AdjustDown函数:

void HeapPop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));
	swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;	
	AdjustDown(php->a, php->size, 0);
}

跟AdjustUp函数同理,对于这个函数,我们传入父亲节点以及要调整的数组的地址,还需要数组元素个数,定义孩子节点:

这里需要用到一条规律:孩子节点=父亲节点*2+1,这是公式父亲节点=(孩子节点-1)/2的逆推

这里我们需要选出孩子节点中的较大者来与父亲节点进行比较,如果前者大于后者,那么就进行交换,将孩子节点作为父亲节点继续判断,直到前者小于等于后者,就结束比较,外层我们使用一个while循环,条件设置为child<元素个数n:

void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		//选出最大的一个孩子
		if (child + 1 < n && a[child] < a[child + 1])
		{
			child = child + 1;
		}
		if (a[parent] < a[child])
		{
			swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

5.判断树是否为空

返回结构体中size是否为0的判断表达式即可:

bool HeapEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
}

6.返回树中元素个数

直接返回size的值即可:

int HeapSize1(HP* php)
{
	assert(php);
	return php->size;
}

7.返回树的顶部元素

这里需要判断树是否为空,在返回数组的第一个元素,也就是树的顶部元素:

HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));
	return php->a[0];
}

数据结构就更新到这里啦!觉得对你有帮助的话可以多多支持作者哦~

——————————————————本文结束——————————————————

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

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

相关文章

Git基本操作快速入门(30min)

Git基本操作快速入门&#xff08;30min&#xff09; 文章目录 Git基本操作快速入门&#xff08;30min&#xff09;1. 建立本地仓库2. 本地仓库链接到远端仓库3. 将本地仓库推送到远端4. Git常用命令 作为一名程序员&#xff0c;使用Github来进行代码的版本管理是必修课&#xf…

汽车IVI中控开发入门及进阶(42):OpenVG

概览: OpenVG是一个无版权、跨平台的API,它为高级用户界面和矢量图形库(如SVG)提供了一个低级硬件加速接口。OpenVG主要针对需要便携式加速高质量矢量图形以获得引人注目的用户界面和文本的消费电子产品、手持设备、可穿戴设备和汽车设备,同时使硬件加速能够在非常低的功…

[1111].集成开发工具Pycharm安装与使用

所有博客大纲 后端学习大纲 Python大纲 1.下载&#xff1a; 官方下载地址 2.安装&#xff1a; 1.双击exe文件&#xff0c;然后下一步选择安装目录 2.选择桌面快捷方式及安装&#xff1a; 3.安装完成 3.启动&#xff1a; 4.设置&#xff1a; 4.1.设置运行时环境&#xff1a;…

Windows11 安装 Ubuntu-20.04,同时安装配置 zsh shell,配置 git 别名(alias),大大提高开发效率

背景&#xff1a;家里配置了一台 Windows 电脑&#xff0c;有时候需要用到 vscode 开发测试一些代码&#xff0c;在使用过程中发现原生 windows 敲代码不是很友好&#xff0c;于是想到配置 wsl&#xff0c;安装 Ubuntu&#xff0c;并安装配置 zsh shell&#xff0c;同时配置 gi…

面试场景题系列:设计限流器

首先看看使用API限流器的好处。 •预防由拒绝服务攻击(Denial of Service&#xff0c;DoS)引起的资源耗尽问题。大型科技公司发布的所有API几乎都强制执行某种形式的限流操作。例如&#xff0c;推特限制每个用户每3小时最多发300条推文。谷歌文档API的默认限制是每个用户每60秒…

Node.js 工具:在 Windows 11 中配置 Node.js 的详细步骤

一、概述 记录时间 [2024-12-25] 本文讲述如何在 Windows 11 中进行 Node.js 工具的安装和配置。 以下是详细的步骤和说明。 二、安装 Node.js 1. 官网下载 通过官网&#xff0c;下载 Node.js&#xff0c;上面有好几种下载方式&#xff0c;文中下载的是 zip 压缩包。 如图&…

DevOps实战:用Kubernetes和Argo打造自动化CI/CD流程(2)

DevOps实战&#xff1a;用Kubernetes和Argo打造自动化CI/CD流程&#xff08;2&#xff09; 背景 架构图 正片开始之前&#xff0c;请一定先熟悉上面的架构图&#xff0c;跟着我的步骤&#xff0c;一步一步执行成功&#xff0c;相信后续根据自己特定的需求定制CI/CD。 需求 …

【Java 学习】详细讲解---包和导包、Scanner类、输入源

1. 包 1.1 什么是包&#xff1f; 举个例子&#xff0c;你和你的同学有不同的家庭&#xff0c;你们都有自己的爸爸妈妈&#xff0c;都有自己的家。在自己的家中你们可以按照自己爱好摆放东西&#xff0c;都互不干扰。但是&#xff0c;假如你们的家都在一起&#xff0c;你们就不…

EasyExcel停更,FastExcel接力

11月6日消息&#xff0c;阿里巴巴旗下的Java Excel工具库EasyExcel近日宣布&#xff0c;将停止更新&#xff0c;未来将逐步进入维护模式&#xff0c;将继续修复Bug&#xff0c;但不再主动新增功能。 EasyExcel以其快速、简洁和解决大文件内存溢出的能力而著称&#xff0c;官方…

Python PDF批量加密工具

Python PDF批量加密工具 1.简介&#xff1a; ‌一个Python写的PDF批量加密工具。PDF批量加密‌是一种保护PDF文件安全性的方法&#xff0c;通过为多个PDF文件设置相同的密码&#xff0c;防止未经授权的用户访问这些文件。批量加密可以大大提高工作效率&#xff0c;特别是在处…

项目2路由交换

背景 某学校为满足日常教学生活需求&#xff0c;推动数字校园的建设&#xff0c;学校有办公楼和学生宿舍楼和服务器集群三块区域&#xff0c;请合理规划IP地址和VLAN&#xff0c;实现企业内部能够互联互通现要求外网能通过公网地址访问服务器集群&#xff0c;学生和老师能正常…

知识梳理笔记--Kerberos 协议

Kerberos 协议概述 Kerberos 是一种计算机网络认证协议&#xff0c;旨在为不安全的网络提供强认证服务。它通过中心化的身份验证系统&#xff08;即 Key Distribution Center&#xff0c;KDC&#xff09;来确保通信双方的身份验证和数据加密。Kerberos 协议主要用于确保计算机系…

9个用于测试自动化的最佳AI测试工具(2024)

选择一款优质的基于生成式AI人工智能的测试工具能够确保测试过程的准确性和效率&#xff0c;从而加速整个软件测试周期。相反&#xff0c;设计不佳的测试工具可能无法发现错误&#xff0c;并可能存在安全问题。它们可能产生误报或漏报&#xff0c;误导开发与测试团队&#xff0…

uni-app 跨端开发精美开源UI框架推荐

&#x1f380;&#x1f380;&#x1f380;uni-app 跨端开发系列 &#x1f380;&#x1f380;&#x1f380; 一、uni-app 组成和跨端原理 二、uni-app 各端差异注意事项 三、uni-app 离线本地存储方案 四、uni-app UI库、框架、组件选型指南 五、uni-app 蓝牙开发 六、uni-app …

【1224】数据结构(sizeof/数组的长度定义/读取字符串函数/线性表长度/左值右值/静态变量/指针与引用)

1.对一维整型数组a的正确说明是 #define SIZE 10 (换行) int a[SIZE];说法是否正确&#xff1f; 正确 数组的SIZE可以用宏定义&#xff0c;但不能用变量 2.如有定义&#xff1a;char str[20];&#xff0c;能将从键盘输入的字符串“How are you”保存到 str 数组的语句是&#x…

强化特种作业管理,筑牢安全生产防线

在各类生产经营活动中&#xff0c;特种作业由于其操作的特殊性和高风险性&#xff0c;一直是安全生产管理的重点领域。有效的特种作业管理体系涵盖多个关键方面&#xff0c;从作业人员的资质把控到安全设施的配备维护&#xff0c;再到特种设备的精细管理以及作业流程的严格规范…

(六)循环神经网络_基本的RNN

一、提出背景 前馈神经网络不考虑数据之间的关联性&#xff0c;网络的输出只和当前时刻网络的输入相关。然而&#xff0c;现实问题中存在着很多序列型的数据&#xff08;文本、语音以及视频等&#xff09;。 例如&#xff1a;室外的温度是随着气候的变化而周期性的变化的&…

Dockerfile的用法

Dockerfile的用法 示例 `Dockerfile`使用 `Dockerfile` 创建 Docker 镜像`Dockerfile` 指令详解其他常用指令总结Dockerfile 是一个文本文件,包含了用于创建 Docker 镜像的一系列指令。这些指令描述了镜像的基础、所安装的软件、文件的复制、环境变量的设置以及其他配置。下面…

60.基于SSM的个人网站的设计与实现(项目 + 论文)

项目介绍 本站是一个B/S模式系统&#xff0c;个人网站是在MySQL中建立数据表保存信息&#xff0c;运用SSMVue框架和Java语言编写。并按照软件设计开发流程进行设计实现充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SSM的网…

B端UI设计规范是什么?

一、B端UI设计规范是什么&#xff1f; B端UI设计规范是一套针对企业级应用界面设计的全面规则和标准&#xff0c;旨在确保产品界面的一致性、可用性和用户体验。 二、B端UI设计规范要素说明 B端UI设计的基本要素包括设计原则、主题、布局、颜色、字体、图标、按钮和控件、交互…