【数据结构】手把手带你玩转线性表

news2024/11/21 0:30:07

前言:

哈喽大家好,我是野生的编程萌新,首先感谢大家的观看。数据结构的学习者大多有这样的想法:数据结构很重要,一定要学好,但数据结构比较抽象,有些算法理解起来很困难,学的很累。我想让大家知道的是:数据结构非常有趣,很多算法是智慧的结晶,我希望大家在学习数据结构的过程是一种愉悦的心情感受。因此我开创了《数据结构》专栏,在这里我将把数据结构内容以有趣易懂的方式展现给大家。

 1.线性表的定义

线性表,听名字我们就能感受到,是具有线一样性质的的表。举个鲜明的例子,当我们在上体育课时,一个班的人都排好队,每一排都有一个打头的,一个收尾的,每个人都知道自己前一个是谁,后面一个是谁,这样就如同一根线一样将他们串在了一起,这就可以称为线性表。线性表是数据结构中最基本的一种,它是由n(n>=0)个具有相同类型的元素组成的有限序列。具体来说,线性表由多个元素组成,每个元素都有一个唯一的前驱元素(除第一个元素外)和唯一的后继元素(除最后一个元素外)。这里我们要强调两个点:

  1. 首先它是一个序列,也就是说,元素之间是有顺序的,若存在多个元素,则第一个元素无前驱,最后一个元素无后继,其他元素都有且仅有一个前驱和后继。如果我们在站队时有同学请假,他的位置将会空出来,那就不能排成一队了(没有补位滴情况)。
  2. 线性表还强调有限,我们的班级人数都是有限的,元素个数当然也是有限的。事实上,在计算机处理的对象都是有限的,那种无限的数列,只存在于数学的概念中。

线性表逻辑结构图大致如下:

 线性表有两种存储方式,一种是顺序存储结构,即将元素依次存储在一块连续的内存中;另一种是链式存储结构,即将元素存储在不连续的内存中,通过指针将它们连接起来。我们前面学过的数组也是顺序表类型,除数组外线性表应用场景还有链表、栈、队列等。线性表是一种常见的数据结构,它具有一对一的关系、存储方式灵活、操作简单高效等特点,广泛应用于各种领域。线性表的优点是操作简单、效率高,但是它的缺点是插入和删除操作需要移动大量的元素,时间复杂度较高。在这一篇博客中我们主要介绍线性表中的顺序存储结构中的顺序表。

2.顺序存储结构——顺序表

顺序表是一种线性数据结构,它通过一组连续的存储单元来存储数据元素,元素之间的关系是一对一的关系。顺序表中的元素在内存中是按照其逻辑顺序依次存放的,可以通过元素在顺序表中的位置(下标)来访问和操作元素。听着怎么感觉顺序表这么像数组呢?顺序表的底层结构就是数组,实现了对数组的封装,实现了常用的增删查改等操作,二者主要区别如下:

  1. 结构差异:顺序表是通过一段连续的存储空间存储元素的线性表,而数组则是一种普通的数据结构,可以存储不连续的元素
  2. 动态性:顺序表的长度可以动态调整,当元素数量超过当前存储空间时,可以进行扩容;而数组的长度是固定的,需要在初始化时指定长度。

  3. 访问效率:由于顺序表的元素是连续存储的,所以在存取元素时效率较高,可以通过下标直接访问;而数组由于是按照索引存储,需要通过索引值来访问元素。

  4. 插入和删除操作效率:顺序表的插入和删除操作需要移动元素,所以效率较低;而数组的插入和删除操作由于不需要移动元素,所以效率较高。

  5. 空间占用:顺序表的存储空间由于需要动态调整,所以可能存在一定的空间浪费;而数组的存储空间是固定的,不会出现空间浪费的情况。

 顺序表有两种实现方式:静态顺序表和动态顺序表。静态顺序表是指在程序设计时,为顺序表分配了一段固定大小的存储空间,不允许进行扩容或缩容的操作。由于静态顺序表的大小是固定的,所以需要在定义时预估数据的最大规模,这可能会导致存储空间的浪费或无法满足需求的问题。下面为静态顺序表:

 动态顺序表是指在程序运行时,可以根据实际的数据规模进行动态扩容或缩容的操作。动态顺序表可以根据需要动态调整存储空间的大小,有效地利用了内存空间。但是,在扩容或缩容时需要进行数据的搬迁,会带来一定的时间开销。下面为动态顺序表:

 顺序表适用于需要频繁访问元素或根据下标查找元素的场景。在元素的插入和删除操作较少,或者已知数据规模的情况下,使用静态顺序表更为合适。在元素的插入和删除操作较多,或者数据规模不确定的情况下,使用动态顺序表更为合适。因为静态顺序表的使用确实不常见,极少情况才会使用静态顺序表,在这里我着重和大家介绍动态顺序表。

3.动态顺序表的的实现

动态顺序表的实现我们需要些一些函数来完成顺序表的初始化、销毁,插入、删除等操作,所以这里我们采用多文件的方式来实现。每一部分的函数都会详细讲解。下面为顺序表的结构代码:

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;  //顺序表有效的个数
	int capacity;  //顺序表的空间大小
}SL;

3.1顺序表的初始化和销毁

我们在主函数通过顺序表的结构来创建一个顺序表,创建完顺序表我们要干什么呢?当然是初始化啦,我们在初始化。在这里我们将顺序表的地址传递给创建的顺序表初始化函数,用一个指针接收顺序表的地址,通过对指针的解引用我们就可以修改顺序表。在顺序表初始化的时候我们要满足:将线性表的长度和容量都设置为0,表示线性表当前为空,将分配的内存空间的起始地址也置空处理。顺序表的初始化函数代码如下:

void SLInit(SL* ps)
{
	ps->a = NULL;
	ps->size = 0;
    ps->capacity = 0;
}

顺序表的销毁是指将顺序表中的数据元素清空,并释放顺序表占用的存储空间,使之成为一个空表。具体步骤为下:首先,释放顺序表中存储数据元素的内存空间,然后,清空顺序表中的数据元素。注意,顺序表的销毁操作可能会导致数据丢失,所以在执行销毁操作之前,应该确保不再需要使用该顺序表中的数据。顺序表的销毁函数代码如下:

void SLDestroy(SL* ps)
{
	if (ps->a)
		free(ps->a);
	ps->size =0;
    ps->capacity = 0;
}

3.2顺序表的插入和删除

在这一小节主要和大家讲解顺序表的尾插、尾删、头插、头删、任意位置插入、任意位置删除操作。我们在顺序表的插入操作时,我们要先判断顺序表是否已满。如果顺序表已满,则需要进行扩容操作,将顺序表的容量增加一定的大小。所以在介绍顺序表的插入之前我们先写一个函数来为我们判断顺序表是否已满。我们要怎样判断顺序表是否满了呢?只需要判断顺序表中的有效元素个数和空间容量是否相等,相等就是满了呗。这个函数实现如下:

void SLCheckcapacity(SL* ps)
{
	if (ps->size == ps->capacity)//空间已经不足以插入数据
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc");
			return 1;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

在上面的代码中我们使用了一个三目运算符来判断顺序表的空间容量是否为0,如果为0,那么就将它的空间容量修改为4,若不是0,那么就将顺序表的空间容量进行2倍扩容(因为在C++的库中就存在顺序表扩容函数,它扩容就是扩大2倍,这里为了对标那个函数,所以就进行2倍扩容)。扩容不一定百分百成功,所以下面对扩容结果进行判断,如果扩容失败就返回realloc失败。

3.2.1顺序表的尾插和尾删

顺序表尾插操作是指将一个新元素插入到顺序表的末尾。顺序表的尾插步骤如下:

  1. 首先,判断顺序表是否已满,如果已满,则无法插入新元素,插入操作失败。
  2. 如果顺序表未满,则将待插入的新元素放入顺序表最后一个位置。
  3. 更新顺序表的长度数值,将长度加1。

 尾插操作的时间复杂度为O(1),即常数时间复杂度,因为无论顺序表的长度是多少,尾插操作都只需要进行一次操作即可完成。顺序表的尾插函数实现代码如下:

void SLpushBack(SL* ps,SLDataType x)
{
	assert(ps != NULL);//判断
	//1.空间足够用直接尾插
	//2.空间不够现申请空间,再进行尾插
	SLCheckcapacity(ps);
	ps->a[ps->size++] = x;//插入数据
}

顺序表的尾删操作指的是删除顺序表中的最后一个元素。顺序表的删除基本可以分为两个步骤:

  1. 找到最后一个元素的位置。顺序表的元素是按照顺序存储在内存中的,所以最后一个元素的位置就是顺序表的长度减一。
  2. 删除最后一个元素。将最后一个元素的位置上的元素删除,并将顺序表的长度减一。

为什么我会说基本可以分为两个步骤呢?当然是因为还有能偷懒的写法(●'◡'●),我们直接将顺序表的有效长度减一不直接就能实现了吗。 尾删时我们还要考虑一个因素顺序表是不是空的,所以我们写一个函数来判断一下:

bool SLisEmpty(SL* ps)
{
	assert(ps);
	return ps->size == 0;
}

首先老样子判断只想顺序表的指针是否指向空值,下面如果ps指向顺序表中的size等于0,那么返回true,否则返回false。我们来实现一下顺序表尾删函数:

void SLpopBack(SL* ps)
{
	assert(ps != NULL);
	assert(!SLisEmpty(ps));
	ps->size--;
}

 3.2.2顺序表的头插和头删

顺序表的头插操作即在顺序表的第一个位置插入一个元素。顺序表的头插步骤如下:

  1. 判断顺序表是否已满,如果已满则无法进行头插操作。
  2. 如果顺序表未满,则将顺序表中的所有元素向后移动一位,为要插入的元素腾出位置。从最后一个元素开始,将其移动到下一个位置,一直到第一个元素移动到第二个位置。
  3. 将要插入的元素放入顺序表的第一个位置。
  4. 更新顺序表的长度。

我们来实现一下顺序表的头插函数:

void SLpushFront(SL* ps, SLDataType x)
{
	assert(ps != NULL);//判断
	//插入情况和尾插相似
	SLCheckcapacity(ps);
	for (SLDataType i = ps->size; i > 0; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[0] = x;
	ps->size++;
}

 头插操作的时间复杂度为O(n),其中n为顺序表中已有元素的个数。因为需要将已有元素后移一位,所以操作的时间复杂度与顺序表中已有元素的个数成正比。

顺序表的头删操作是指删除顺序表中第一个元素的操作。顺序表的头删的步骤如下:

  1. 判断顺序表是否为空,如果为空则无法进行头删操作。
  2. 如果顺序表不为空,则将第一个元素移除。
  3. 将后面的元素依次往前移动一位,覆盖掉被删除元素的位置。从第二个元素开始,将其移动到前一个位置,一直到最后一个元素位置。
  4. 更新顺序表的长度。

 我们来实现一下顺序表的头删函数:

void SLpopFront(SL* ps)
{
	assert(ps != NULL);
	for (SLDataType i = 0; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

头删操作的时间复杂度也为O(n),因为需要将后面的元素往前移动一位,所以操作的时间复杂度与顺序表中已有元素的个数成正比。

3.2.3 顺序表的任意插入和任意删除

顺序表中的任意插入操作是指在任意位置插入一个元素。任意位置插入的具体步骤为下:

  1. 判断顺序表是否已满,如果已满则无法插入新元素,给出相应提示。
  2. 判断插入位置是否合法,即在顺序表的范围内,如果不合法则给出相应提示。
  3. 如果插入位置合法,需要将插入位置以及其后面的元素后移一个位置,为新元素腾出空间。
  4. 将要插入的元素放入插入位置。
  5. 更新顺序表的长度。

 我们来实现一下顺序表的任意插入函数:

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckcapacity(ps);
	int end = ps->size;
	while (end >= pos)
	{
		ps->a[end] = ps->a[end-1];
		--end;
	}
	ps->a[pos-1] = x;
	ps->size++;
}

当然有的朋友喜欢任意位置之后插入,其实现代码如下:

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckcapacity(ps);
	int end = ps->size-1;
	while (end >= pos)
	{
		ps->a[end+1] = ps->a[end];
		--end;
	}
	ps->a[pos] = x;
	ps->size++;
}

顺序表的任意位置删除操作是指在顺序表中删除指定位置的元素。任意位置删除的具体操作步骤如下:

  1. 首先判断删除位置的有效性。
  2. 将指定位置后面的所有元素向前移动一位。从删除位置开始,将删除位置后面的所有元素向前移动一位,覆盖掉删除的元素。可以使用一个循环来实现这个步骤。

  3. 将顺序表的长度减1,表示顺序表中元素的个数减少了一个。

我们来实现一下任意位置删除函数:

void SLErase(SL* ps, int pos)
{
	assert(ps != NULL);
	assert(pos >= 0 && pos < ps->size);
	for (SLDataType i = pos; i < ps->size - 1; i++)
	{
		ps->a[i-1] = ps->a[i];
	}
	ps->size--;
}

任意位置之后删除代码实现:

void SLErase(SL* ps, int pos)
{
	assert(ps != NULL);
	assert(pos >= 0 && pos < ps->size);
	for (SLDataType i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

4.多文件实现顺序表 

SeqList.h文件:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;  //顺序表有效的个数
	int capacity;  //顺序表的空间大小
}SL;
void SLInit(SL* ps);//顺序表初始化
void SLDestroy(SL* ps);//顺序表的删除
void SLpushBack(SL* ps,SLDataType x);//尾插数据
void SLpushFront(SL* ps, SLDataType x);//头插数据
void SLpopBack(SL* ps);//尾删数据
void SLpopFront(SL* ps);//头删数据
void SLInsert(SL* ps, int pos, SLDataType x);//任意位置插入数据
void SLErase(SL* ps, int pos);//任意位置删除数据

SeqList.c文件:

#include"SeqList.h"
void SLInit(SL* ps)
{
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}
void SLDestroy(SL* ps)
{
	if (ps->a)
		free(ps->a);
	ps->size = ps->capacity = 0;
}
void SLCheckcapacity(SL* ps)
{
	if (ps->size == ps->capacity)//空间已经不足以插入数据
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc");
			return 1;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}
void SLpushBack(SL* ps,SLDataType x)
{
	assert(ps != NULL);//判断
	//1.空间足够用直接尾插
	//2.空间不够现申请空间,再进行尾插
	SLCheckcapacity(ps);
	ps->a[ps->size++] = x;//插入数据
}
void SLpushFront(SL* ps, SLDataType x)
{
	assert(ps != NULL);//判断
	//插入情况和尾插相似
	SLCheckcapacity(ps);
	for (SLDataType i = ps->size; i > 0; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[0] = x;
	ps->size++;
}
bool SLisEmpty(SL* ps)
{
	assert(ps);
	return ps->size == 0;
}
void SLpopBack(SL* ps)
{
	assert(ps != NULL);
	assert(!SLisEmpty(ps));
	ps->size--;
}
void SLpopFront(SL* ps)
{
	assert(ps != NULL);
	for (SLDataType i = 0; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}
void print(SL* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	SLCheckcapacity(ps);
	int end = ps->size-1;
	while (end >= pos)
	{
		ps->a[end+1] = ps->a[end];
		--end;
	}
	ps->a[pos] = x;
	ps->size++;
}
void SLErase(SL* ps, int pos)
{
	assert(ps != NULL);
	assert(pos >= 0 && pos < ps->size);
	for (SLDataType i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

 test.c文件:

#include"SeqList.h"
void Test()
{
	SL sl;
	SLInit(&sl);
	SLpushBack(&sl, 1);
	SLpushBack(&sl, 2);
	SLpushBack(&sl, 3);
	SLpushBack(&sl, 4);
	SLpushBack(&sl, 5);
	print(&sl);
	SLErase(&sl, 2);
	print(&sl);
	SLInsert(&sl, 2, 6);
	print(&sl);
}
int main()
{
	Test();
	return 0;
}

我这里简单写一个函数来测试,测试结果为:

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

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

相关文章

windows安装mysql8.0.36

MySQL :: Download MySQL Installer (Archived Versions)下载地址在上面选择一个版本&#xff0c;任意版本&#xff0c;有个小要求&#xff0c;8以上哦&#xff0c;是mysql windows安装版本 接下来是完整的流程操作 下载好就是这个样子 选择安装 在一个盘符中创建文件夹&…

英语学习笔记8——What‘s your job?

What’s your job? 你是做什么工作的&#xff1f; 词汇 Vocabulary policeman 男警察 policewoman 女警察 police n. 警力 集合名词&#xff0c;永表复数 西方国家警察管的事很多。交警&#xff0c;刑警&#xff0c;武警一般不分开。 taxi driver 出租车司机 taxi / cab n.…

buuctf-misc题目练习三

荷兰宽带数据泄露 BIN 文件&#xff0c;也称为二进制文件&#xff0c;是一种压缩文件格式&#xff0c;可以 包含图像和视频等信息 , 并被许多应用程序用于各种目的。 RouterPassView是一个找回路由器密码的工具。 大多数现代路由器允许备份到一个文件路由器的配置&#xff0c…

2024.05.10作业

TCP服务器 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QTcpSocket> #include <QList> #include <QMessageBox> #include <QDebug>QT_BEGIN_NAMESPACE namespace Ui { class Widget; …

SpringCloud生态体系介绍

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用Spring Boot的开发风格做到一键启动和部署。 SpringC…

15 华三华为链路聚合综述

1 链路聚合简介 以太网链路聚合通过将多条以太网物理链路捆绑在一起形成一条以太网逻辑链路&#xff0c;实现增加链路带宽的目的&#xff0c;同时这些捆绑在一起的链路通过相互动态备份&#xff0c;可以有效地提高链路的可靠性。 2 成员端口的状态 聚合组内的成员端口具有以下…

ChatGLM3-6B部署与微调及微调后使用

记录ChatGLM3-6B部署及官方Lora微调示例详细步骤及如何使用微调后的模型进行推理 一、下载代码 使用git clone 命令下载源码 git clone https://github.com/THUDM/ChatGLM3.git 如图所示 二、下载模型 模型权重文件从魔塔进行下载&#xff0c;不需要翻墙。权重文件比较大&…

Linux(利用gdb进行调试)

gdb: gdb是GNU debugger的缩写&#xff0c;是编程调试工具。 gdb功能 1.启动程序&#xff0c;可以按照用户自定义的要求随心所欲的运行程序。 2.让被调试的程序在用户所指定的调试的断点处停住 (断点可以是条件表达式)。 3.当程序停住时&#xff0c;可以检查此时程序中所发…

云衔科技成为卓豪Zoho中国区代理商,开启智能化企业管理新篇章

每一家企业数字化转型&#xff0c;都在寻求通过技术创新实现业务的飞跃。为了更好地服务于中国企业的数字化转型需求&#xff0c;云衔科技荣幸宣布正式成为卓豪Zoho中国区代理商&#xff0c;这一强强联合将为市场带来全新的数字化解决方案与服务体验&#xff0c;共同开启中国企…

【PyTorch单点知识】深入理解与应用转置卷积ConvTranspose2d模块

文章目录 0. 前言1. 转置卷积概述2. nn.ConvTranspose2d 模块详解2.1 主要参数2.2 属性与方法 3. 计算过程&#xff08;重点&#xff09;3.1 基本过程3.2 调整stride3.3 调整dilation3.4 调整padding3.5 调整output_padding 4. 应用实例5. 总结 0. 前言 按照国际惯例&#xff0…

什么是FMEA的分析范围?——FMEA软件

免费试用FMEA软件-免费版-SunFMEA FMEA的分析范围广泛而深入&#xff0c;涵盖了产品设计、制造过程、供应链管理以及使用和维修等多个方面。 产品设计是FMEA分析的重要一环。在设计阶段&#xff0c;FMEA能够帮助工程师识别潜在的设计缺陷&#xff0c;并预测这些缺陷可能对产品…

Bugku Crypto 部分题目简单题解(三)

where is flag 5 下载打开附件 Gx8EAA8SCBIfHQARCxMUHwsAHRwRHh8BEQwaFBQfGwMYCBYRHx4SBRQdGR8HAQ0QFQ 看着像base64解码 尝试后发现&#xff0c;使用在线工具无法解密 编写脚本 import base64enc Gx8EAA8SCBIfHQARCxMUHwsAHRwRHh8BEQwaFBQfGwMYCBYRHx4SBRQdGR8HAQ0QFQ tex…

ArcGIS10.2能用了10.2.2不行了(解决)

前两天我们的推文介绍了 ArcGIS10.2系列许可到期解决方案-CSDN博客文章浏览阅读2次。本文手机码字&#xff0c;不排版了。 昨晚&#xff08;2021\12\17&#xff09;12点后&#xff0c;收到很多学员反馈 ArcGIS10.2系列软件突然崩溃。更有的&#xff0c;今天全单位崩溃。​提示许…

智慧公厕,小民生里的“大智慧”!

公共厕所是城市社会生活的基础设施&#xff0c;而智慧公厕则以其独特的管理模式为城市居民提供更优质的服务。通过智能化的监测和控制系统&#xff0c;智慧公厕实现了厕位智能引导、环境监测、资源消耗监测、安全防范管理、卫生消杀设备、多媒体信息交互、自动化控制、自动化清…

OpenCV 入门(四)—— 车牌号识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

DiskCatalogMaker for Mac:高效管理磁盘文件助手

DiskCatalogMaker for Mac&#xff0c;助您高效管理磁盘文件&#xff0c;让文件整理变得轻而易举&#xff01;这款软件以其出色的性能和人性化的设计&#xff0c;赢得了广大Mac用户的喜爱。 DiskCatalogMaker支持多种磁盘格式&#xff0c;让您轻松管理硬盘、U盘、光盘等存储设备…

LaTeX公式学习笔记

\sqrt[3]{100} \frac{2}{3} \sum_{i0}^{n} x^{3} \log_{a}{b} \vec{a} \bar{a} \lim_{x \to \infty} \Delta A B C

基于Springboot的微乐校园管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的微乐校园管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

Python尝试安装 pyaudio 时遇到的错误信息表示安装过程失败,原因是找不到 Python.h 头文件

环境&#xff1a; Python 3.8.10 WSL2 问题描述&#xff1a; 尝试安装 pyaudio 时遇到的错误信息表示安装过程失败&#xff0c;原因是找不到 Python.h 头文件 error: subprocess-exited-with-error Building wheel for pyaudio (pyproject.toml) did not run successfully…

组合模式(结构型)

目录 一、前言 二、透明组合模式 三、安全组合模式 四、总结 一、前言 组合模式(Composite Pattern)是一种结构型设计模式&#xff0c;将对象组合成树形结构以表示“部分-整体”得层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 组合模式由以下角色组成…