顺序表的代码实现

news2024/9/8 23:39:36

顺序表的代码实现

  • 1.认识什么是顺序表
    • 1.1顺序表的优缺点
  • 2.实现顺序表代码准备
  • 3.顺序表的代码实现
    • 3.1 顺序表结构体的定义
    • 3.2 顺序表的初始化
    • 3.3 顺序表的销毁
    • 3.4 顺序表的输出打印
    • 3.5顺序表的扩容
    • 3.6 顺序表的头部插入(头插)
    • 3.7 顺序表的头部删除(头删)
    • 3.8 顺序表的尾部插入(尾插 )
    • 3.9 顺序表的尾部删除(尾删)
    • 3.10 在指定位置之前插入数据
    • 3.11 删除指定位置的数据
    • 3.12 查找数据
  • 4.完整代码

1.认识什么是顺序表

  • 顺序表是一种基本的数据结构,属于线性表的一种具体实现形式。在顺序表中,数据元素被存储在计算机内存中的一系列连续的存储位置上,这些位置通常是由数组提供的。这意味着顺序表中的每个元素都占据一个固定的存储空间,并且可以通过其索引(或位置)直接访问。

总的来说:顺序表的底层是数组,是对数组的封装,实现了常用的增删改查等接口。因为底层是数组,所以在逻辑结构上一定是连续的,物理结构上不一定连续。

1.1顺序表的优缺点

顺序表的优缺点

2.实现顺序表代码准备

为了保持代码的清晰和模块化,在实现代码前我们需要定义三个文件:
SeqList.h:(函数的声明
1.这是一个头文件,它定义了顺序表的结构和对外提供的函数接口。
2.其他程序可以通过包含这个头文件来使用顺序表的功能。
3.头文件提供了一个清晰的接口文档,说明了如何使用顺序表,同时也隐藏了内部实现细节。
SeqList.c:(函数的实现
2.这是源文件,包含了顺序表的实际实现代码。
3.它实现了头文件中声明的所有函数。
Test.c:(测试函数的功能
1.这是一个测试文件,用来验证顺序表的正确性。
2.在这个文件中,你会写一些测试代码,调用顺序表的函数并检查结果是否符合预期。

3.顺序表的代码实现

在实现顺序表时需要用到的头文件:
<stdio.h>,<stdlib.h>,<assert.h>

  1. <stdio.h>
  • 用途:会使用 printf() 和 scanf() 等函数,用于控制台输出和输入。

  • 应用场景:

    • 在调试阶段,可以使用 printf() 来输出顺序表的状态,例如在插入、删除操作前后打印顺序表的内容。
    • 使用 scanf() 或者其他输入函数来从用户那里获取数据,例如插入新元素的值。
  1. <stdlib.h>
  • 用途:提供内存管理相关的函数,如 malloc(), calloc(), realloc(), 和 free()。
  • 应用场景:
    • 当需要扩展顺序表的容量时,可以使用 realloc() 来调整已分配内存的大小。
    • 当销毁顺序表时,使用 free() 来释放分配给 data 的内存。
  1. <assert.h>
  • 用途:在编译时检查条件是否为真,如果条件不满足,则会终止程序执行,并给出错误信息。
  • 应用场景:
    • 在函数入口处检查参数的有效性,例如在 SLInsert() 和 SLDelete() 函数中检查索引是否有效。

3.1 顺序表结构体的定义

  • SeqList.h中定义(动态)顺序表的基本数据结构
#include<stdio.h>
#include<stdlib.h>//开辟空间要用
#include<assert.h>//断言用
typedef int SLDataType;//重复定义int,便于修改顺序表中的顺序类型
typedef struct SeqList
{
	SLDataType* arr;//指向一块连续的空间
	int size;//顺序表的有效数据个数
	int capacity;//顺序表的可以容纳的数据容量个数
}SL://将结构体命名为SL,更加简洁,便于后期的创建

typedef int SLDataType;:这一行定义了一个类型别名SLDataType,它实际上就是int类型。这里使用类型别名是为了让数据结构更加通用和灵活,如果将来需要改变顺序表中元素的数据类型(比如从整型改为浮点型或者其他类型),只需要在这里修改SLDataType的定义即可,而不需要去修改整个数据结构的实现代码。

SLDataType* arr;:这是一个指向SLDataType类型的指针,代表了顺序表中存储数据的数组。arr指向的是一块连续的内存区域,这块区域可以存储多个SLDataType类型的元素。

int size;:定义一个整型变量,表示顺序表当前实际包含的元素数量。size的值不会超过capacity,并且在插入和删除元素时会相应地增减。

int capacity;:一个整型变量,表示顺序表当前的容量,即arr所指向的数组能容纳的最大元素数量。capacity反映了顺序表当前分配的内存大小,当size接近capacity时,以便重新分配更大的内存空间以避免溢出。

3.2 顺序表的初始化

  • 先在SeqList.h中声明初始化函数SLInit,然后在SeqList.c中实现对顺序表的初始化,定义一个初始化函数SLInit,将data初始化为空NULL,将有效数据个数size和顺序表大小capacity初始化为0;

.h文件中声明:

// 声明初始化顺序表的函数
void SLInit(SeqList *list);

.c文件中实现:

//顺序表的初始化
void SLInit(SL* ps)
{
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

test文件中测试

#include "SeqList.h"
void SLTest01()
{
	SL sl;
	SLInit(&sl);//初始化
}
int main()
{
	SLTest01();
	return 0;
}

调试

3.3 顺序表的销毁

  • 先在.h文件中声明销毁函数,然后在.c文件中实现,销毁通常是释放分配给顺序表的内存,如将data指针指向的内存释放,并将其置为空。

.h中声明:

// 声明销毁顺序表的函数
void SLDestroy(SeqList *ps);

.c中实现:

//销毁
void SLDestroy(SL* ps)
	if (ps->a)//判断顺序表(数组)是否为空;等价于(ps->a != NULL)
	{
		free(ps->a);//若不为空,则释放内存
	}
	ps->a = NULL;//释放内存后置空
	ps->size = ps->capacity = 0;
}

test中测试

#include "SeqList.h"
void SLTest01()
{
	SL sl;
	SLInit(&sl);//初始化

	SLDestroy(&sl);//销毁
}
	
int main()
{
	SLTest01();
	return 0;
}

销毁测试

3.4 顺序表的输出打印

  • 遍历顺序表,打印顺序表数据:
//顺序表的打印
void SLPrint(SL ps)
{
	for (int i = 0; i < ps.size; i++)
	{
		printf("%d ",ps.a[i]);
	}
	printf("\n");
}

3.5顺序表的扩容

  • 在插入数据时,要保证顺序表的空间足够,否则就要对顺序表进行扩大,以保证插入操作的有效性,所以定义SLCheckCapacity函数对顺序表的大小进行检查,以便及时对空间大小进行调整。

.h中声明:

//扩容
void SLCheckCapacity(SL* ps);

.c中实现:

void SLCheckCapacity(SL* ps)//检查空间是否足够
{
	if (ps->capacity == ps->size)//若不够,则动态开辟内存
	{
		int newCapacity = ps->capacity == 0 ? INIT_CAPACITY : 2 * ps->capacity;//创建临时变量newCapacity来开辟内存,保证a不会因为realloc开辟失败返回空,导致a的数据丢失
		SLDataType* temp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		if (temp == 0)
		{
			perror("realloc error!");//内存开辟失败的提示
			return 1;//退出程序
		}//开辟内存成功
		ps->a = temp;//确保内存开辟成功后赋值给a
		ps->capacity = newCapacity;//更新空间大小
	}
}

3.6 顺序表的头部插入(头插)

  1. 函数首先检查传入的指针 ps 是否为 NULL。如果是 NULL,则触发断言失败,程序终止。防止对无效指针进行操作。
  2. 然后,调用 SLCheckCapacity 函数来确保顺序表有足够的空间来容纳新插入的元素。如果空间不足,则调整数组的大小。
  3. 接着,使用一个循环从最后一个元素开始,将每个元素向后移动一个位置。循环条件是从
    ps->size(有效数据个数)到 1。每次循环时,ps->a[i] 的值被赋值给 ps->a[i + 1],将所有元素都向后移动了一位,腾出 ps->a[0] 这个位置。
  4. 将新元素 x 放在 ps->a[0] 的位置上,进行头插。
  5. 插入元素后,更新元素总数,数量增加 1,即 ps->size 的值加 1

.h中声明:

//头插
void SLPushFront(SL* ps, SLDataType x);

.c中实现:

//头插
void SLPushFront(SL* ps, SLDataType x)//头插
{
  assert(ps);
  SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够

  //让顺序表中原来的数据整体向后移动一位
  for (int i = ps->size - 1; i >= 0; i--)
  {
  	ps->a[i + 1] = ps->a[i];//ps->a[1] = ps->a[0]
  }
  ps->a[0] = x;
  ps->size++;//头插后,顺序表中数据个数有所变化,所以需要++更新
}

3.7 顺序表的头部删除(头删)

  1. 参数检查:
    • 检查传入的指针 ps 是否为 NULL。如果是 NULL,断言失败,防止对无效指针进行操作。
    • 接着检查 ps->size 是否大于 0,即顺序表中是否有元素可以删除。如果没有元素,则断言失败,防止从空顺序表中删除元素。
  2. 元素移动:
    • 使用一个循环从第一个元素开始,将每个元素向前移动一个位置。循环条件是从 0
      ps->size - 2。每次循环时,ps->a[i + 1] 的值被赋值给 ps->a[i]。这样就能将所有元素都向前移动了一位,覆盖了原本位于 ps->a[0] 的元素,实现了头删操作。
  3. 更新大小:
    • 删除元素后,顺序表中的元素总数减少 1,因此 ps->size 的值减 1

.h中声明:

void SLPopFront(SL* ps);//头删

.c中实现:

//头删
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	//最前面的数据删除后,后面的数据整体向前挪一位
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];//arr[size - 2] = arr[size - 1]
	}
	ps->size--;//删除后对有效数据进行更新
}

test中测试:
在这里插入图片描述

3.8 顺序表的尾部插入(尾插 )

  1. 参数检查:
    • assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,程序会终止。
  2. 容量检查:
    • 调用 SLCheckCapacity(ps) 函数来确保顺序表有足够的空间来容纳新插入的元素。如果空间不足,SLCheckCapacity 会调整数组的大小。
  3. 插入新元素:
    • 使用 ps->a[ps->size++] = x;,将新元素 x 插入到数组 ps->a 的当前有效大小的位置,也就是数组的最后一个位置。最后,ps->size 的值加 1,更新顺序表中元素数量的变化。

.h中声明:

//尾插
void SLPushBack(SL* ps, SLDataType x);

.c中是实现:

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够
	ps->a[ps->size++] = x;//尾插数据,并更新有效数据的个数
	//ps->a[ps->size] = x;
	//ps->size++;
}

3.9 顺序表的尾部删除(尾删)

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
    • 使用 assert(ps->size) 确保顺序表中至少有一个元素。如果 ps->size 为 0,说明顺序表为空,无法删除元素,也会断言失败。
  2. 删除元素:
    • 由于顺序表是通过数组实现的,删除尾部元素的操作非常简单,只需将 ps->size 减少 1 即可。
    • 在 C 语言中,数组的索引是从 0 开始的,因此 ps->a[ps->size - 1] 表示顺序表中的最后一个元素。
    • 删除最后一个元素后,ps->size 应该减 1,更新顺序表中有效的数据个数。
  3. 清理尾部元素(理解即可):
    • 代码注释中将最后一个元素置为 -1,但这不是必需的。因为 ps->size 已经减少了 1,所以 ps->a[ps->size](即原本的 ps->a[ps->size - 1])不再是有效索引,即使保留原有的值也不会影响后续的操作。
    • 因此,代码中并没有执行 ps->a[ps->size - 1] = -1; 这一行,而是直接减少 ps->size 的值。

.h中声明:

void SLPopBack(SL* ps);//尾删

.c中实现:

//尾删
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	//assert断言,确保顺序表不能为空(顺序表不为空,顺序表中的有效数据size也不为空)
	//ps->a[size - 1] = -1;//尾删的数据不论是否置为-1,都不影响增删查改
	ps->size--;
}

test中测试:
尾插尾删测试

3.10 在指定位置之前插入数据

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
    • 使用 assert(pos >= 0 && pos <= ps->size) 确保指定的插入位置 pos 是有效的。位置 pos 必须是非负的,并且不能超过当前顺序表的有效大小 ps->size。
  2. 容量检查:
    • 调用 SLCheckCapacity(ps) 函数来确保顺序表有足够的空间来容纳新插入的元素。如果空间不足,SLCheckCapacity 会调整数组的大小以满足插入需求。
  3. 元素移动:
    • 使用一个循环从最后一个有效元素开始,将每个元素向后移动一个位置,直到达到目标位置 pos。
    • 循环条件是从 ps->size 到 pos,即 for (int i = ps->size; i > pos; i–)。将所有在 pos 之后的元素都向后移动一位,为新元素腾出空间。
  4. 插入新元素:
    • 将新元素 x 插入到 ps->a[pos] 的位置,即指定的位置。
  5. 更新大小:
    • 插入元素后,顺序表中的元素总数增加 1,更新ps->size 的值加 1。

.h中声明:

//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);

.c中实现:

//指定位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);

	//插入数据,判断空间够不够
	SLCheckCapacity(ps);

	//让数据整体向后挪一位
	for (int i = ps->size;i >pos;i--)
	{
		ps->a[i] = ps->a[i - 1];//a[pos + 1] = a[pos];
	}
	ps->a[pos] = x;
	ps->size++;
}

test中测试:
指定位置前插入测试

3.11 删除指定位置的数据

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
    • 使用 assert(pos >= 0 && pos < ps->size) 确保指定的删除位置 pos 是有效的。位置 pos 必须是非负的,并且不能超过当前顺序表的有效大小 ps->size。
  2. 元素移动:
    • 使用一个循环从指定位置 pos 开始,将每个元素向前移动一个位置,直到达到顺序表的倒数第二个元素。
    • 循环条件是从 pos 到 ps->size - 1,即 for (int i = pos; i < ps->size - 1; i++)。将所有在 pos 之后的元素都向前移动一位,覆盖被删除元素的位置。
  3. 更新大小:
    删除元素后,顺序表中的元素总数减少 1,更新ps->size 的值减 1。
    .h中声明:
void SLErase(SL* ps, int pos);//指定位置删除

.c中实现:

//指定位置删除数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos; i < ps-> size - 1;i++)
	{
		//删除后后面的数据向前挪一位
		ps->a[i] = ps->a[i + 1];//a[size - 2] = a[size - 1];
	}
	ps->size--;
}

test中测试:
指定位置删除测试

3.12 查找数据

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
  2. 遍历顺序表:
    • 使用一个循环从顺序表的第一个元素开始遍历整个顺序表。
    • 循环条件是从 0 到 ps->size - 1,即 for (int i = 0; i < ps->size; i++)。因为 ps->size 表示顺序表中有效元素的数量,所以有效元素的索引范围是从 0 到 ps->size - 1。
  3. 比较数据:
    • 在循环体内,使用 if (ps->a[i] == x) 来检查当前元素 ps->a[i] 是否等于要查找的数据 x。
    • 如果找到匹配的元素,则返回该元素的下标 i。
  4. 未找到数据:
    • 如果循环结束后都没有找到匹配的数据,函数返回 -1,表示数据 x 不在顺序表中。

.h中声明:

int SLFind(SL* ps, SLDataType x);//指定位置查找

.c中实现:

//查找数据
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		//找到了
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;//返回一个无效下标,习惯上返回-1;
}

test中测试:
查找数据测试

4.完整代码

SeqList.h文件:

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define INIT_CAPACITY 4

typedef int SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{
    SLDataType* a;
    int size;     // 有效数据个数
    int capacity; // 空间容量
}SL;

//初始化和销毁
void SLInit(SL* ps);//初始化
void SLDestroy(SL* ps);//销毁

void SLPrint(SL ps);//顺序表的打印

//扩容
void SLCheckCapacity(SL* ps);

//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPopBack(SL* ps);//尾删
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPopFront(SL* ps);//头删

//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);//指定位置插入
void SLErase(SL* ps, int pos);//指定位置删除
int SLFind(SL* ps, SLDataType x);//指定位置查找

SeqList.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"

void SLInit(SL* ps)//顺序表的初始化
{
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

void SLCheckCapacity(SL* ps)//检查空间是否足够
{
	if (ps->capacity == ps->size)//若不够,则动态开辟内存
	{
		int newCapacity = ps->capacity == 0 ? INIT_CAPACITY : 2 * ps->capacity;//创建临时变量newCapacity来开辟内存,保证a不会因为realloc开辟失败返回空,导致a的数据丢失
		SLDataType* temp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		if (temp == 0)
		{
			perror("realloc error!");//内存开辟失败的提示
			return 1;//退出程序
		}//开辟内存成功
		ps->a = temp;//确保内存开辟成功后赋值给a
		ps->capacity = newCapacity;//更新空间大小
	}
}


//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够
	ps->a[ps->size++] = x;//尾插数据,并更新有效数据的个数
	//ps->a[ps->size] = x;
	//ps->size++;
}

//头插
void SLPushFront(SL* ps, SLDataType x)//头插
{
	assert(ps);
	SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够

	//让顺序表中原来的数据整体向后移动一位
	for (int i = ps->size - 1; i >= 0; i--)
	{
		ps->a[i + 1] = ps->a[i];//ps->a[1] = ps->a[0]
	}
	ps->a[0] = x;
	ps->size++;//头插后,顺序表中数据个数有所变化,所以需要++更新
}

//尾删
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	//assert断言,确保顺序表不能为空(顺序表不为空,顺序表中的有效数据size也不为空)
	//ps->a[size - 1] = -1;//尾删的数据不论是否置为-1,都不影响增删查改
	ps->size--;
}

//头删
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	//最前面的数据删除后,后面的数据整体向前挪一位
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];//arr[size - 2] = arr[size - 1]
	}
	ps->size--;//删除后对有效数据进行更新
}


//顺序表的打印
void SLPrint(SL ps)
{
	for (int i = 0; i < ps.size; i++)
	{
		printf("%d ",ps.a[i]);
	}
	printf("\n");
}


void SLDestroy(SL* ps)//销毁
{
	if (ps->a)//判断顺序表(数组)是否为空;等价于(ps->a != NULL)
	{
		free(ps->a);//若不为空,则释放内存
	}
	ps->a = NULL;//释放内存后置空
	ps->size = ps->capacity = 0;
}

//指定位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);

	//插入数据,判断空间够不够
	SLCheckCapacity(ps);

	//让数据整体向后挪一位
	for (int i = ps->size;i >pos;i--)
	{
		ps->a[i] = ps->a[i - 1];//a[pos + 1] = a[pos];
	}
	ps->a[pos] = x;
	ps->size++;
}

//指定位置删除数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	for (int i = pos; i < ps-> size - 1;i++)
	{
		//删除后后面的数据向前挪一位
		ps->a[i] = ps->a[i + 1];//a[size - 2] = a[size - 1];
	}
	ps->size--;
}

//查找数据
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		//找到了
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;//返回一个无效下标,习惯上返回-1;
}

Test.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
void SLTest01()
{
	SL sl;
	SLInit(&sl);//初始化
	//增删查改操作
	
	头插测试
	//SLPushFront(&sl, 0);
	//SLPrint(sl);
	//SLPushFront(&sl, 2);
	//SLPrint(sl);
	//SLPushFront(&sl, 5);
	//SLPrint(sl);

	//头删测试
	//SLPopFront(&sl);
	//SLPrint(sl);
	//SLPopFront(&sl);
	//SLPrint(sl);
	//SLPopFront(&sl);
	//SLPrint(sl);

	//尾插测试
	SLPushBack(&sl, 1);
	SLPrint(sl);
	SLPushBack(&sl, 3);
	SLPrint(sl);
	SLPushBack(&sl, 1);
	SLPrint(sl);
	SLPushBack(&sl, 4);	
	SLPrint(sl);

	//尾删测试
	//SLPopBack(&sl);
	//SLPrint(sl);
	//SLPopBack(&sl);
	//SLPrint(sl);
	//SLPopBack(&sl);
	//SLPrint(sl);
	//SLPopBack(&sl);
	//SLPrint(sl);

	printf("\n");

	//指定位置插入测试
	SLInsert(&sl, 0, 520);
	SLPrint(sl);
	SLInsert(&sl, 5, 20);
	SLPrint(sl);
	SLInsert(&sl, 2, 1314);
	SLPrint(sl);

	//指定位置删除测试
	SLErase(&sl, 0);
	SLPrint(sl);
	SLErase(&sl, 2);
	SLPrint(sl);
	SLErase(&sl, 1);
	SLPrint(sl);

	//顺序表查找数据
	int find = SLFind(&sl, 40);
	if (find >= 0)
	{
		printf("找到了!下表为%d\n",find);
	}
	else
	{
		printf("没找到!");
	}

	SLDestroy(&sl);//销毁
}
	
int main()
{
	SLTest01();
	return 0;
}

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

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

相关文章

会话存储、本地存储,路由导航守卫、web会话跟踪、JWT生成token、axios请求拦截、响应拦截

1、会话存储、本地存储 前端浏览器中存储用户信息&#xff0c;会话存储、本地存储、cookie 会话存储&#xff08;sessionStorage&#xff09;&#xff1a;会话期间存储&#xff0c;关闭浏览器后&#xff0c;数据就会销毁 sessionStorage.setItem("account",resp.d…

Unity Apple Vision Pro 开发:如何把 PolySpatial 和 Play To Device 的版本从 1.2.3 升级为 1.3.1

XR 开发社区&#xff1a; SpatialXR社区&#xff1a;完整课程、项目下载、项目孵化宣发、答疑、投融资、专属圈子 &#x1f4d5;教程说明 本教程将介绍如何把 Unity 的 PolySpatial 和 Play To Device 版本从 1.2.3 升级为 1.3.1。 &#x1f4d5;Play To Device 软件升级 ht…

科学设计程序员面试内容,破解“八股文”之弊

“八股文”在实际工作中是助力、阻力还是空谈&#xff1f; 作为现在各类大中小企业面试程序员时的必问内容&#xff0c;“八股文”似乎是很重要的存在。但“八股文”是否能在实际工作中发挥它“敲门砖”应有的作用呢&#xff1f;有IT人士不禁发出疑问&#xff1a;程序员面试考…

数据结构之线性表(顺序表的实现)

目录 一、线性表的原理 二、线性表的实现&#xff08;顺序表&#xff09; 1.定义顺序表 2.初始化顺序表 3.判断顺序表是否为空 4.获取顺序表的长度 5.向顺序表中插入元素 6.删除指定位置的元素 7.遍历顺序表 8.得到指定位置的元素 三、打印测试功能 1.测试 2.结果…

【Ant Design Vue的更新日志】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步! 以下是Ant Design Vue的更新日志 版本1.7.0(发布日期:2023年4月) …

python之代码简化式(列表、字典生成式,递归函数,迭代器(iter)和生成器(yield)、匿名函数(lambda)的使用)(12)

文章目录 前言1、列表、字典生成式2、递归函数2.1 python中代码的递归深度&#xff08;扩展&#xff09; 3、拓展&#xff1a;迭代器和生成器3.1 迭代器&#xff08;iter&#xff09;3.2 生成器&#xff08;yield&#xff09; 4、匿名函数&#xff08;lambda&#xff09;4.1 ma…

康师傅JAVA核心内容

链接&#xff1a;康师傅JAVA核心内容 (qq.com)

LeetCode刷题笔记第682题:棒球比赛

LeetCode刷题笔记第682题&#xff1a;棒球比赛 题目&#xff1a; 想法&#xff1a; 遍历输入的列表&#xff0c;按照规则将分数和操作依次进行&#xff0c;存储在新建的列表中&#xff0c;最终输出列表中的元素和&#xff0c;代码如下&#xff1a; class Solution:def calPo…

Ubuntu、centos、openEuler安装docker

目录 1.在 Ubuntu 上安装 Docker 1. 1 更新软件包 1. 2 安装必要的依赖 1.3 添加 Docker 的 GPG 密钥 1.4 添加 Docker 仓库 1.5 更新软件包 1.6 安装 Docker 1.7 启动并启用 Docker 服务 1.8 验证安装 1.9 运行测试容器 1.10 非 root 用户运行 Docker 2.在 CentOS…

前端基于 axios 实现批量任务调度管理器 demo

一、背景介绍 这是一个基于 axios 实现的批量任务调度管理器的 demo。它使用了axios、promise 等多种技术和原理来实现批量处理多个异步请求&#xff0c;并确保所有请求都能正确处理并报告其状态。 假设有一个场景&#xff1a;有一个任务列表&#xff0c;有单个任务的处理功能…

OpenGL学习 1

一些唠叨&#xff1a; 很多时候&#xff0c;都被Live2d吸引&#xff0c;去年想给网页加个live2d看板娘&#xff0c;结果看不懂live2d官方给的SDK&#xff0c;放弃了。今天又想弄个live2d桌宠&#xff0c;都已经在网上找到Python 的 Live2D 拓展库了&#xff0c;并提供了用QT实现…

领航者-跟随者编队算法 定义+特性+原理+公式+Python示例代码(带详细注释)

文章目录 引言定义特性基本原理和公式推导基本原理公式推导运动模型领航者的控制跟随者的控制 示例推导 实现步骤和代码实现实现步骤Python代码实现&#xff08;带详细注释&#xff09;代码运行结果代码和图表说明 应用案例优化和挑战优化挑战 结论 引言 在现代科技的发展中&a…

PointCLIP: Point Cloud Understanding by CLIP

Abstract 近年来&#xff0c;基于对比视觉语言预训练(CLIP)的零镜头和少镜头学习在二维视觉识别中表现出了令人鼓舞的效果&#xff0c;该方法在开放词汇设置下学习图像与相应文本的匹配。然而&#xff0c;通过大规模二维图像-文本对预训练的CLIP是否可以推广到三维识别&#x…

【状语从句】

框架 概念&#xff0c;特点主将从现连接词时间条件地点结果方式让步原因目的比较省略倒装 解读 1【概念&#xff0c;特点】 一个完整的句子&#xff0c;去修饰另一个完整句子中的动词&#xff0c;称为状语从句&#xff1b;特点&#xff1a;从句完整&#xff0c;只用考虑连接词是…

扩展------正向代理和反向代理怎么理解?

今天看博客园&#xff0c;突然看到正向代理和反向代理&#xff0c;发现自己还不会就稍微研究了一下。 正向代理----(看做是服务员) 当我们进饭店吃饭&#xff0c;我们不可能会直接去后厨叫厨师给我们做菜&#xff0c;而是通过服务员去通知&#xff0c;这个就叫做正向代理。 再…

keras在GPU环境下配置,conda虚拟环境并安装TensorFlow,cudatoolkit,cudann和jupyter等

前言&#xff1a;要有版本意识 在我个人的多次配置环境过程中&#xff0c;很多时候失败或者后序出现问题&#xff0c;往往都是版本不匹配的问题。所以在本次安装中&#xff0c;提前重点了解了下版本匹配情况。各位千万不要跳过这部分&#xff0c;因为这不仅是基础知识了解的过…

君子学习,是为了修养自己

98天 保护自己最好的方式&#xff1a; 恢复良知的明和诚&#xff0c;就能照见万物&#xff0c;能常觉、常照&#xff0c;任何东西都无所遁形。&#xff08;相信直觉&#xff09; 君子学习&#xff0c;是为了修养自己。 从不担忧别人会欺骗自己&#xff0c;只是永远不欺骗自己的…

docker笔记7-dockerfile

docker笔记7-dockerfile 一、dockerfile介绍二、dockerfile指令三、构建自己的镜像 一、dockerfile介绍 Dockerfile是用来构建Docker镜像的构建文件&#xff0c;是由一系列命令和参数构成的脚本。 以下是常用的 Dockerfile 关键字的完整列表和说明&#xff1a; 二、docker…