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

顺序表详解


  • 💓 博客主页:江池俊的博客
  • ⏩ 收录专栏:数据结构探索
  • 👉专栏推荐:✅C语言初阶之路 ✅C语言进阶之路
  • 💻代码仓库:江池俊的代码仓库
  • 🔥编译环境:Visual Studio 2022
  • 🎉欢迎大家点赞👍评论📝收藏⭐

在这里插入图片描述

文章目录

  • 🚀线性表
  • 🚀顺序表
    • 🚨概念及结构
      • 🎈. 静态顺序表:使用定长数组存储元素。
      • 🎈. 动态顺序表:使用动态开辟的数组存储。
  • 🚀接口实现
    • 📌有哪些接口呢
    • 📌准备工作
    • 📌初始化
    • 📌扩容
    • 📌顺序表打印
    • 📌顺序表销毁
    • 📌尾插
    • 📌尾删
    • 📌头插
    • 📌头删
    • 📌指定pos下标位置插入数据
    • 📌删除pos位置的数据
    • 📌查找
    • 📌修改pos位置的数据
  • 🚀源码
    • 🌴SeqList.h 文件
    • 🌴SeqList.c 文件
    • 🌴Test.c 文件


🚀线性表

【维基百科】 线性表(英语:Linear List)是由n(n≥0)个数据元素(结点)a[0],a[1],a[2]…,a[n-1]组成的有限序列。

其中:

  • 数据元素的个数n定义为表的长度 = “list”.length() (“list”.length() = 0(表里没有一个元素)时称为空表)
  • 将非空的线性表(n>=1)记作:(a[0],a[1],a[2],…,a[n-1])
  • 数据元素a[i](0≤i≤n-1)只是个抽象符号,其具体含义在不同情况下可以不同

一个数据元素可以由若干个数据项组成。数据元素称为记录,含有大量记录的线性表又称为文件。这种结构具有下列特点:存在一个唯一的没有前驱的(头)数据元素;存在一个唯一的没有后继的(尾)数据元素;此外,每一个数据元素均有一个直接前驱和一个直接后继数据元素。

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

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

在这里插入图片描述


🚀顺序表

🚨概念及结构

【维基百科】 顺序表是在计算机内存中数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。

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

🎈. 静态顺序表:使用定长数组存储元素。

在这里插入图片描述

🎈. 动态顺序表:使用动态开辟的数组存储。

在这里插入图片描述


🚀接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。

所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表

这里的接口其实就是 接口函数 ,这些 接口函数 提供了顺序表的各种基本操作,允许我们对顺序表进行 增、删、查、改 等操作。

📌有哪些接口呢

// 基本 增删查改 接口 --- 命名风格是跟着STL走的,方便后续学习STL
// 顺序表初始化
void SeqListInit(SL* psl);
// 检查空间,如果满了,进行增容 --> 扩容
void SLCheckCapacity(SL* psl);
// 顺序表尾插
void SeqListPushBack(SL* psl, SLDataType x);
// 顺序表头插
void SeqListPushFront(SL* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SL* psl);
// 顺序表头删
void SeqListPopFront(SL* psl);
// 顺序表查找
int SeqListFind(SL* psl, SLDataType x);
//顺序表的修改
void SeqListModify(SL* psl,int pos, SLDataType x);
// 顺序表在pos位置插入x(可以实现头插和尾插)
void SeqListInsert(SL* psl, int pos, SLDataType x);
// 顺序表删除pos位置的值(可以实现头删和尾删)
void SeqListErase(SL* psl, int pos);
// 顺序表打印
void SeqListPrint(SL* psl);
// 顺序表销毁
void SeqListDestroy(SL* psl);

接下来我将带着大家一 一实现这些接口。

📌准备工作

在写顺序表前,我们需要创建工程,这里为了让大家养成模块化的好习惯,我们尽量将代码分成三个文件来写。这里我打开的编译器是 vs 2022,在资源管理器的 头文件 中创建 SeqList.h 文件,此文件作用主要是为了存储各种头文件和接口函数的声明以及顺序表结构体的创建;在源文件中创建 SeqList.c 文件用来实现接口函数,Test.c 文件用来测试顺序表的各个接口。具体如下图所示:

在这里插入图片描述
注意:

  • 为了能够在顺序表中方便地存储各种类型的数据,我们可以使用 typedef 将要存储的数据类型重命名为 SLDataType ,这样在定义顺序表的数据类型时只需要使用 SLDataType 就行了,修改数据类型时只需要修改 typedef 后面跟着的这个数据类型,这样就大大方便了对不同类型数据的存储。
  • 类似的,为了方便结构体的定义和使用,我们也可以使用 typedef 将结构体定义一个简单的别名为 SL
#pragma once#include<stdio.h>
#include<stdlib.h> // NULL、size_t
#include<assert.h>// 静态的顺序表:使用定长数组存储元素。
// 特点:如果满了就不让插入
// 缺点:N给小了不够用,给多了浪费,这个很难确定
//#define N 100
//typedef int SLDataType; // 给int取别名
//struct SeqList // 创建顺序表
//{
//	SLDataType a[N]; // 定长数组
//	int size; // 存储的有效数据的个数
//};// 动态顺序表:使用动态开辟的数组存储。
//typedef double SLDatatype;
typedef int SLDataType; //重定义类型名称,方便顺序表对不同类型的数据的存储和操作
typedef struct SeqList // 创建顺序表
{SLDataType* a; //指向动态开辟的数组int size;       // 存储的有效数据的个数int capacity;   // 容量空间大小
}SL; //将结构体类型取别名为 SL

📌初始化

这里我们实现动态顺序表,所以刚开始时我们可以假设给定顺序表的大小为 4(即能存放4个元素),不够就扩容,顺序表中刚开始是没有元素的。

//顺序表初始化
void SeqListInit(SL* psl)
{//防止psl为空指针(即防止传错结构体地址)assert(psl);psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//判断能否成功开辟空间if (psl->a == NULL){perror("malloc fail");//将系统错误信息输出到屏幕return;}psl->capacity = 4;psl->size = 0;
}

📌扩容

在后续对顺序表进行操作过程中我们会插入数据,如果顺序表空间不够,我们就需要使用 realloc 函数进行扩容。
这里newcapacity表示扩容后能存放的元素个数(即空间的容量),tmp表示的是扩容后的空间的地址,如果顺序表的空间为空,就给定能存放4个元素的空间;如果空间不够,就在原来空间的基础上,增加 1 倍的空间(这样也依然无法避免空间的部分浪费,所以就有了链表,后续文章我会为大家带来)。

// 扩容 ---> 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl)
{if (psl->size == psl->capacity){//如果没有空间或者空间不足,就扩容int newcapacity = (psl->capacity == 0 ? 4 : psl->capacity * 2);SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newcapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1); //退出程序}psl->a = tmp;psl->capacity = newcapacity;}
}

📌顺序表打印

打印比较简单,这里我们只需要依次遍历每一个节点就行。

//打印
void SeqListPrint(SL* psl)
{//防止psl为空指针(即防止传错结构体地址)assert(psl);//遍历for (int i = 0; i < psl->size; i++){printf("%d ", psl->a[i]);}printf("\n");
}

📌顺序表销毁

因为是动态开辟的,所以如果空间不用我们就需要销毁掉。如果不销毁会存在内存泄漏的风险,所以这里我们使用free函数释放开辟的动态空间,并把有效数据个数和容量空间都置为0

//销毁
void SeqListDestroy(SL* psl)
{assert(psl);free(psl->a);psl->a = NULL;psl->size = 0;psl->capacity = 0;
}

📌尾插

尾插就是在最后一个元素的后面插入一个元素(即在size下标位置处插入数据),但要注意的是当capacity空间满了就需要扩容,因此我们要调用SLCheckCapacity函数。

//尾插
void SeqListPushBack(SL* psl, SLDataType x)
{assert(psl);//psl->a[psl->size] = x;//psl->size++;SLCheckCapacity(psl); // 检查扩容psl->a[psl->size++] = x;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, psl->size, x);
}

📌尾删

尾删其实就是将顺序表最后一个数据删去,要实现这一操作其实只需要将有效数据个数减一就可以了(即size--),但是在尾删之前要先判断顺序表中是否有元素,如果没有元素就没有必要删了。

//尾删
void SeqListPopBack(SL* psl)
{assert(psl);//温柔的处理方式//if (psl->size > 0)//{//	psl->size--;//}//else//{//	printf("没有数据能够再删了!\n");//		exit(-1); //退出程序//}//暴力的处理方式assert(psl->size > 0);//确保顺序表中有数据psl->size--;//复用pos下标位置删除数据的函数//SeqListErase(psl, psl->size - 1);
}

📌头插

头插操作其实就是在顺序表下表为 0 的位置插入数据,然后 size++,但是在此之前要判断顺序表容量空间是否已满,所以要先调用 SLCheakCapacity 函数。在这里插入图片描述

//头插
void SeqListPushFront(SL* psl, SLDataType x)
{assert(psl);SLCheckCapacity(psl);//挪动数据int end = psl->size -1;while (end >= 0){psl->a[end + 1] = psl->a[end];end--;}psl->a[0] = x;psl->size++;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, 0, x);
}

📌头删

头删的实现其实只需要将顺序表开头后面的数据依次往前挪动,然后将 size-- 就可以了,这里要从前往后挪,如果从后往前挪数据会被覆盖。注意:这里与尾删类似,在头删之前要先判断顺序表中是否有元素,如果没有元素就没有必要删了。
在这里插入图片描述

//头删
void SeqListPopFront(SL* psl)
{assert(psl);assert(psl->size > 0);//有数据才能删,没数据就会报错int begin = 1;while (begin < psl -> size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;//复用pos效标位置删除数据的函数//SeqListErase(psl, 0);
}

📌指定pos下标位置插入数据

我们只需要将顺序表中pos位置到最后的数据依次往后挪动(从后往前挪),然后将pos下标位置的数据改为要插入的数据,最后 size++ 即可。但是我们依然要判断是否满容,所以在插入数据前要调用 SLCheakCapacity 函数。同时我们也要判断pos位置是否合理,防止越界访问。

//指定pos下标位置插入数据
void SeqListInsert(SL* psl, int pos, SLDataType x)
{assert(psl);//if (pos > psl->size || pos < 0)//{//	printf("pos的下标位置越界");//	return;//}//暴力的方式处理(pos下标不能越界)assert(pos >= 0 && pos <= psl->size);//如果没有空间或者空间不足,就扩容SLCheckCapacity(psl);//挪动数据int end = psl->size - 1;while (end >= pos){psl->a[end + 1] = psl->a[end];end--;}psl->a[pos] = x;psl->size++;
}

📌删除pos位置的数据

与头删类似,我们只需要将pos位置后的数据依次往前挪动将pos位置处的数据覆盖,然后再 size-- 就可以了。但是要判断pos位置是否合理,防止越界访问。

//删除pos位置的数据(结合SeqListFind函数可以删除指定的数据)
void SeqListErase(SL* psl, int pos)
{assert(psl);assert(pos >= 0 && pos < psl->size);//pos位置需要有数据//挪动数据int begin = pos + 1;while (begin < psl->size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;
}

📌查找

这个比较简单,我们只需要遍历一遍顺序表,查找相应数据,若找到,就返回下标,若没找到,就返回-1。

//查找,找到了返回下标,没找到返回-1
int SeqListFind(SL* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; i++){if (psl->a[i] == x){return i;}}return -1;
}

📌修改pos位置的数据

通过pos下标直接修改

//修改pos位置的数据
void SeqListModify(SL* psl, int pos, SLDataType x)
{assert(psl);assert(pos >= 0 && pos < psl->size);psl->a[pos] = x;
}

🚀源码

🌴SeqList.h 文件

#pragma once#include<stdio.h>
#include<stdlib.h>//NULL、size_t
#include<assert.h>// 静态的顺序表:使用定长数组存储元素。
// 特点:如果满了就不让插入
// 缺点:N给小了不够用,给多了浪费,这个很难确定
//#define N 10000
//typedef int SLDatatype; // 给int取别名
//struct SeqList // 创建顺序表
//{
//	SLDatatype a[N]; // 定长数组
//	int size; // 存储的有效数据的个数
//};
//静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪
//费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实
//现动态顺序表。// 动态顺序表:使用动态开辟的数组存储。
//typedef double SLDatatype;
typedef int SLDataType; //重定义类型名称,方便顺序表对不同类型的数据的存储和操作
typedef struct SeqList
{SLDataType* a; //指向动态开辟的数组int size;       // 存储的有效数据的个数int capacity;   // 容量空间大小
}SL;// 基本 增删查改 接口 --- 命名风格是跟着STL走的,方便后续学习STL
// 顺序表初始化
void SeqListInit(SL* psl);// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl);// 顺序表尾插
void SeqListPushBack(SL* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SL* psl);
// 顺序表头插
void SeqListPushFront(SL* psl, SLDataType x);
// 顺序表头删
void SeqListPopFront(SL* psl);
// 顺序表查找
int SeqListFind(SL* psl, SLDataType x);
// 顺序表在pos位置插入x(可以实现头插和尾插)
void SeqListInsert(SL* psl, int pos, SLDataType x);
// 顺序表删除pos位置的值(可以实现头删和尾删)
void SeqListErase(SL* psl, int pos);// 顺序表打印
void SeqListPrint(SL* psl);
// 顺序表销毁
void SeqListDestroy(SL* psl);//顺序表的修改
void SeqListModify(SL* psl, int pos, SLDataType x);

🌴SeqList.c 文件

#include"SeqList.h"//void SeqListInit(SL* psl)
//{
//	psl->a = NULL;
//	psl->size = 0;
//	psl->capacity = 0;
//}//顺序表初始化
void SeqListInit(SL* psl)
{//防止psl为空指针(即防止传错结构体地址)assert(psl);psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//判断能否成功开辟空间if (psl->a == NULL){perror("malloc fail");//将系统错误信息输出到屏幕return;}psl->capacity = 4;psl->size = 0;
}
//销毁
void SeqListDestroy(SL* psl)
{assert(psl);free(psl->a);psl->a = NULL;psl->size = 0;psl->capacity = 0;
}
//打印
void SeqListPrint(SL* psl)
{assert(psl);for (int i = 0; i < psl->size; i++){printf("%d ", psl->a[i]);}printf("\n");
}
// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl)
{assert(psl);if (psl->size == psl->capacity){//如果没有空间或者空间不足,就扩容int newcapacity = (psl->capacity == 0 ? 4 : psl->capacity * 2);SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newcapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);//退出程序}psl->a = tmp;psl->capacity = newcapacity;}
}
//尾插
void SeqListPushBack(SL* psl, SLDataType x)
{assert(psl);//psl->a[psl->size] = x;//psl->size++;SLCheckCapacity(psl);//检查扩容psl->a[psl->size++] = x;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, psl->size, x);
}
//尾删
void SeqListPopBack(SL* psl)
{assert(psl);//温柔的处理方式//if (psl->size > 0)//{//	psl->size--;//}//else//{//	printf("没有数据能够再删了!\n");//		exit(-1);//}//暴力的处理方式assert(psl->size > 0);//确保顺序表中有数据psl->size--;//复用pos下标位置删除数据的函数//SeqListErase(psl, psl->size - 1);
}
//头插
void SeqListPushFront(SL* psl, SLDataType x)
{assert(psl);SLCheckCapacity(psl);//挪动数据int end = psl->size -1;while (end >= 0){psl->a[end + 1] = psl->a[end];end--;}psl->a[0] = x;psl->size++;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, 0, x);
}
//头删
void SeqListPopFront(SL* psl)
{assert(psl);assert(psl->size > 0);//有数据才能删,没数据就会报错int begin = 1;while (begin < psl -> size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;//复用pos效标位置删除数据的函数//SeqListErase(psl, 0);
}
//查找,找到了返回下标,没找到返回-1
int SeqListFind(SL* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; i++){if (psl->a[i] == x){return i;}}return -1;
}
//指定pos下标位置插入数据
void SeqListInsert(SL* psl, int pos, SLDataType x)
{assert(psl);//if (pos > psl->size || pos < 0)//{//	printf("pos的下标位置越界");//	return;//}//暴力的方式处理(pos下标不能越界)assert(pos >= 0 && pos <= psl->size);//如果没有空间或者空间不足,就扩容SLCheckCapacity(psl);//挪动数据int end = psl->size - 1;while (end >= pos){psl->a[end + 1] = psl->a[end];end--;}psl->a[pos] = x;psl->size++;
}//删除pos位置的数据(结合SeqListFind函数可以删除指定的数据)
void SeqListErase(SL* psl, int pos)
{assert(psl);assert(pos >= 0 && pos < psl->size);//pos位置需要有数据//挪动数据int begin = pos + 1;while (begin < psl->size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;
}//修改pos位置的数据
void SeqListModify(SL* psl, int pos, SLDataType x)
{assert(psl);assert(pos >= 0 && pos < psl->size);psl->a[pos] = x;}

🌴Test.c 文件

#define _CRT_SECURE_NO_WARNINGS 1#include "SeqList.h"int main()
{SL s;SeqListInit(&s);SeqListPushBack(&s, 1);SeqListPushBack(&s, 2);SeqListPushBack(&s, 3);SeqListPushBack(&s, 4);SeqListPushBack(&s, 5);SeqListPushBack(&s, 6);//尾插SeqListPopBack(&s);//尾删SeqListPushFront(&s, 0);//头插SeqListPopFront(&s);//头删SeqListInsert(&s, 2, 8);//指定pos下标为2的位置插入数据8SeqListPrint(&s);//打印SeqListDestroy(&s);//销毁return 0;
}

💨 今天的分享就到这里,如果觉得博主的文章还不错的话, 请👍三连支持一下博主哦🤞

相关文章:

顺序表详解

&#x1f493; 博客主页&#xff1a;江池俊的博客⏩ 收录专栏&#xff1a;数据结构探索&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f525;编译环境&#xff1a;Visual Studio 2022&#x1f38…...

基于RabbitMQ的模拟消息队列之六——网络通信设计

自定义基于TCP的应用层通信协议。实现客户端对服务器的远程调用 编写服务器及客户端代码 文章目录 基于TCP的自定义应用层协议一、请求1.请求格式2.创建Request类 二、响应1.响应格式2.创建Response类 三、客户端-服务器交互四、type五、请求payload1.BasicAruguments(方法公共…...

算法:数组中的最大差值---“打擂台法“

文章来源&#xff1a; https://blog.csdn.net/weixin_45630258/article/details/132737088 欢迎各位大佬指点、三连 1、题目&#xff1a; 给定一个整数数组 nums&#xff0c;找出给定数组中两个数字之间的最大差值。要求&#xff0c;第二个数字必须大于第一个数字。 2、分析特…...

三种方式查看 JVM 垃圾收集器

一、引言 不同版本的 JVM 默认使用的垃圾收集器是不同的&#xff0c;目前的新生代和老年代的垃圾收集器如下图所示&#xff0c;新生代和老年代之间的连线表示这些垃圾收集器可以进行搭配使用 垃圾收集器的名字和 JVM 里面的参数对照表如下&#xff0c;即在 JVM 里面并不是存储的…...

React中函数式组件与类组件有何不同?

Function Component 与 Class Component 有何不同 目录 Function Component 与 Class Component 有何不同 文章核心观点&#xff1a; 解释一下&#xff1a; 总结&#xff1a; 文章核心观点&#xff1a; Function components capture the rendered values.函数式组件捕获…...

windows11安装docker时,修改默认安装到C盘

1、修改默认安装到C盘 2、如果之前安装过docker&#xff0c;请删除如下目录&#xff1a;C:\Program Files\Docker 3、在D盘新建目录&#xff1a;D:\Program Files\Docker 4、winr&#xff0c;以管理员权限运行cmd 5、在cmd中执行如下命令&#xff0c;建立软联接&#xff1a; m…...

python模块之 aiomysql 异步mysql

mysql安装教程 mysql语法大全 python 模块pymysql模块&#xff0c;连接mysql数据库 一、介绍 aiomysql 是一个基于 asyncio 的异步 MySQL 客户端库&#xff0c;用于在 Python 中与 MySQL 数据库进行交互。它提供了异步的数据库连接和查询操作&#xff0c;适用于异步编程环境 …...

开开心心带你学习MySQL数据库之第八篇

索引和事务 ~~ 数据库运行的原理知识 面试题 索引 索引(index) > 目录 索引存在的意义,就是为了加快查找速度!!(省略了遍历的过程) 查找速度是快了&#xff0c;但是付出了一定的代价!! 1.需要付出额外的空间代价来保存索引数据 2.索引可能会拖慢新增,删除,修改的速度 ~~ …...

yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题

1&#xff1a;yml 配置 spring:datasource:dynamic:datasource:master:url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncodingUTF-8&useUnicodetrue&useSSLfalse&tinyInt1isBitfalse&allowPublicKeyRetrievaltrue&serverTimezoneUTCusername: ro…...

yolov5运行过程遇到的小问题(随时更新)

1.关于git的问题 解决办法&#xff1a;插入下面代码 import os os.environ["GIT_PYTHON_REFRESH"] "quiet"2.页面太小无法完成操作 解决办法: 如果不好使再考虑降低Batch_Size大小或者调整虚拟内存可用硬盘空间大小&#xff01;&#xff08;调整虚拟内存…...

使用FabricJS创建Image对象的JSON表示

本篇文章介绍一下如何创建图像的 JSON 表示形式 使用 FabricJS 的对象。我们可以通过创建一个实例来创建一个 Image 对象 织物.图像。由于它是FabricJS的基本元素之一&#xff0c;我们也可以轻松地 通过应用角度、不透明度等属性来自定义它。为了创建 JSON Image 对象的表示&am…...

【牛客刷题】反转固定区间链表、每k个节点一组反转

链表内指定区间反转_牛客题霸_牛客网 ListNode* reverseList(ListNode* head, ListNode* tail) {ListNode* pre nullptr;ListNode* cur head;while (cur ! tail) { 最后cur就是tailListNode* temp cur->next;cur->next pre;pre cur;cur temp;}return pre;}ListNode…...

算法:数组常见套路1---双指针、取模、打擂台法

文章来源&#xff1a; https://blog.csdn.net/weixin_45630258/article/details/132738318 欢迎各位大佬指点、三连 一、数组的合并–双指针[快慢指针] 1、题目&#xff1a; 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0…...

App 出海实践:Google Play 结算系统

作者&#xff1a;业志陈 现如今&#xff0c;App 出海热度不减&#xff0c;是很多公司和个人开发者选择的一个市场方向。App 为了实现盈利&#xff0c;除了接入广告这种最常见的变现方式外&#xff0c;就是通过提供各类虚拟商品或者是会员服务来吸引用户付费了&#xff0c;此时 …...

国际慈善日 | 追寻大爱无疆,拓世科技集团的公益之路

每年的9月5日&#xff0c;是联合国大会正式选定的国际慈善日。这一天的设立&#xff0c;旨在通过提高公众对慈善活动的意识&#xff0c;鼓励慈善公益活动通过各种形式在全球范围内得到增强和发展。这是一个向慈善公益事业致敬的日子&#xff0c;同时也是呼吁全球团结一致共同发…...

关于DNS的一些认识

目录 什么是DNS&#xff1f; 一台具有单个DNS的机器可以拥有多个地址吗&#xff1f; 一台计算机可以有多个属于不同顶级域的DNS名字吗&#xff1f; 什么是DNS&#xff1f; DNS是域名系统&#xff08;Domain Name System&#xff09;的缩写&#xff0c;它是互联网中用于将域名…...

游戏性能优化

Unity性能优化主要包括以下方面&#xff1a; 1.渲染性能 。包括减少Draw Calls、减少三角面数、使用LOD、使用批处理技术、减少实时光源等&#xff0c;以提高游戏的帧率和渲染效率。 2.内存性能 。包括使用对象池、使用合适的纹理、使用异步加载资源等&#xff0c;以减少内存占…...

公开游戏、基于有向图的游戏

目录 〇&#xff0c;背景 一&#xff0c;公开游戏、策梅洛定理 1&#xff0c;公开游戏 2&#xff0c;策梅洛定理 二&#xff0c;有向图游戏 1&#xff0c;狭义有向图游戏 2&#xff0c;广义有向图游戏 3&#xff0c;狭义有向图游戏的SG数 4&#xff0c;Bash Game 力扣…...

CSS学习笔记05

CSS笔记05 定位 position CSS 属性position - 用于指定一个元素在文档中的定位方式。top&#xff0c;right&#xff0c;bottom 和 left 属性则决定了该元素的最终位置。position 有以下常用的属性值&#xff1a; position: static; - 默认值。指定元素使用正常的布局行为&am…...

Linux查看指定端口是否被占用

在Linux中&#xff0c;可以使用多种方法来检查一个特定端口&#xff08;例如3306&#xff0c;通常由MySQL使用&#xff09;是否被占用&#xff1a; 使用netstat命令: 如果系统中已安装了netstat&#xff0c;可以使用以下命令检查3306端口&#xff1a; netstat -tuln | grep 330…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

Python的__call__ 方法

在 Python 中&#xff0c;__call__ 是一个特殊的魔术方法&#xff08;magic method&#xff09;&#xff0c;它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时&#xff08;例如 obj()&#xff09;&#xff0c;Python 会自动调用该对象的 __call__ 方法…...

CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14

什么是 Pattern Matching&#xff08;模式匹配&#xff09; ❝ 模式匹配就是一种“描述式”的写法&#xff0c;不需要你手动判断、提取数据&#xff0c;而是直接描述你希望的数据结构是什么样子&#xff0c;系统自动判断并提取。❞ 你给的定义拆解&#xff1a; ✴ Instead of …...