深入解析顺序表:揭开数据结构的奥秘,掌握顺序表的精髓


  • 💓 博客主页:江池俊的博客
  • ⏩ 收录专栏:数据结构探索
  • 👉专栏推荐:✅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;
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【业务功能篇99】微服务-springcloud-springboot-电商订单模块-生成订单服务-锁定库存

八、生成订单 一个是需要生成订单信息一个是需要生成订单项信息。具体的核心代码为 /*** 创建订单的方法* param vo* return*/private OrderCreateTO createOrder(OrderSubmitVO vo) {OrderCreateTO createTO new OrderCreateTO();// 创建订单OrderEntity orderEntity build…

【ESP32】带 log 记录的 malloc 动态申请内存,用于debug 调试查找报错原因

本文章以ESP32为依托&#xff0c;旨在解决在【嵌入式工程】开发过程中&#xff0c;在动态申请内存这部分&#xff0c;由于 malloc 之后&#xff0c;忘记 free 释放&#xff0c;造成内存溢出导致 MCU重启的问题 &#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好…

linux安装nacos2.2.0

1、使用docker拉取镜像&#xff1a;docker pull nacos/nacos-server:v2.2.0 2、下载官方配置文件&#xff1a;https://github.com/alibaba/nacos/releases 3、修改配置文件的数据库连接信息&#xff0c;修改完成后将配置文件移至挂载目录/home/shixp/docker/nacos/conf&#xf…

统计表和流程分析,也能同屏呈现_三叠云

表单统计&流程分析 路径 表单设计 >> 表单设置 >> 拓展设置 >> 表单统计 功能简介 新增表单统计、流程分析功能&#xff08;Beta版&#xff09;。可在当前列表&#xff0c;直接看到表单的统计表和流程分析数据统计图表。 1. 统计表&#xff1a;统计…

实时美颜的背后:视频直播美颜SDK的算法与原理

美颜技术的应用范围已经广泛扩展&#xff0c;从自拍照片到视频直播&#xff0c;都可以看到它的踪迹。然而&#xff0c;视频直播的实时性要求比静态图像高得多。要实现实时美颜&#xff0c;必须克服许多技术挑战。这就是视频直播美颜SDK的用武之地。 一、实时美颜的挑战 实时…

如何使用CMD恢复删除的分区?

分区删除后可以恢复吗&#xff1f; 磁盘分区旨在二级存储上创建一个或多个区域&#xff0c;然后你可以单独管理每个区域&#xff0c;这些区域就是分区。因此&#xff0c;对新安装的存储设备进行分区是很重要的环节&#xff0c;只有分区后才可以在这些设备上创建文件并保存数…

Spring Boot 下载文件(word/excel等)文件名中文乱码问题|构建打包不存在模版文件(templates等)

Spring Boot 下载文件(word/excel等)文件名中文乱码问题&#xff5c;构建打包不存在模版文件(templates等) 准备文件&#xff0c;这里我放在resource下的templates路径 在pom中配置构建打包的资源&#xff0c;更新maven 如果使用了assembly打包插件这样配置可能仍不生效&#…

理财是什么?怎样学习理财?

大家好&#xff0c;我是财富智星&#xff0c;今天跟大家分享一下理财是什么&#xff1f;怎样学习理财的方法。 一、理财的基本原则 1、理财应注重投资而不是投机&#xff0c;要与时间为友。 让我们先考虑以下问题&#xff1a;什么样的回报才算是真正的高回报&#xff1f;假设有…

2023年一级建造师建设工程经济真题

2023年一级建造师建设工程经济真题 1.根据《建设工程工程量清单计价规范》规定&#xff0c;代表专业工程的项目编码是 ()。 A、1&#xff0c;2 B、3&#xff0c;4 C、5&#xff0c;6 D、7&#xff0c;8&#xff0c;9 【答案】B 2.某公司希望所投资项目在第5年末回收1000万…

LoGoNet:基于局部到全局跨模态融合的精确 3D 目标检测

论文地址&#xff1a;https://arxiv.org/abs/2303.03595 论文代码&#xff1a;https://github.com/sankin97/LoGoNet 论文背景 激光雷达传感器点云通常是稀疏的&#xff0c;无法提供足够的上下文来区分远处的区域&#xff0c;从而造成性能次优。 激光雷达-摄像机融合方法在三…

[NLP] LLM---扩充词表LLama2-构建中文tokenization

使用SentencePiece的除了从0开始训练大模型的土豪和大公司外&#xff0c;大部分应该都是使用其为当前开源的大模型扩充词表&#xff0c;比如为LLama扩充通用中文词表&#xff08;通用中文词表&#xff0c;或者 垂直领域词表&#xff09;。那这部分工作有没有意义呢&#xff1f;…

实验室电磁铁EM4的技术参数

锦正茂EM4电磁铁可以通过更换电磁铁极头在一定范围内改善磁场的大小和磁场的均匀度 &#xff0c;并且可以通过调整极头间距改变磁场的大小&#xff0c;该种类型的电磁铁能够很好的与客户设计的磁场平台兼容。主要用于磁滞现象研究、磁化系数测量、霍尔效应研究、磁光实验、磁场…

WebSocket的优缺点

WebSocket的优缺点 1. WebSocket概念 1.1 WebSocket优点 低延迟全双工长期运行双向实时通信 1.2 什么是心跳机制 为了保持WebSocket稳定的长连接,在建立连接后,服务器和客户端之间需要通过心跳包来保持连接状态,以防止连接因长时间没有数据传输而被切断. 心跳包是一直特殊…

学会使用MySQL数据库(1)数据库相关背景了解

目录 什么是数据库 客户端-服务器&#xff08;Client-Server&#xff09; 数据库分类 MySQL服务器安装 内存和外存 什么是数据库 存储数据用文件就可以了&#xff0c;为什么还要弄个数据库? 文件保存数据有以下几个缺点&#xff1a; 文件的安全性问题文件不利于数据查询…

Spring框架中的Resource接口是什么,以及它在加载和访问资源时的关键作用

文章目录 什么是 Resource 接口&#xff1f;使用 Resource 加载资源使用 Resource 访问文件系统资源总结 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;Java框架 ✨文章内…

没出息的项目经理的5大表现

大家好&#xff0c;我是老原。 都说&#xff0c;30岁的项目经理凶猛如狼&#xff0c;40岁的项目经理狡猾如狐。 实际上&#xff0c;又有多少项目经理能做到这般。 有多少项目经理&#xff0c;兢兢业业工作个几年&#xff0c;最后还是守着一亩三分地&#xff0c;既没有升职加…

PMP认证可以用来干什么呢?

PMP(项目管理专业人士&#xff09;认证是一项国际上广为认可的专业认证&#xff0c;具有以下几个重要用途和好处&#xff1a; 1. 提升职业竞争力&#xff1a; PMP认证是项目管理领域具有权威性和声誉的认证之一。持有PMP认证可以证明你具备了相关知识、技能和经验&#xff0c…

【LeetCode75】第五十四题 咒语和药水的成功对数

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们两个数组&#xff0c;要我们找出第一个数组中每个元素能和另一个数组的元素匹配的数量。匹配的条件是乘积大于特定的值。 那么…

[SSM]MyBatisPlus拓展

五、拓展篇 5.1逻辑删除 在电商网站中&#xff0c;我们会上架很多商品&#xff0c;这些商品下架以后&#xff0c;我们如果将这些商品从数据库中删除&#xff0c;那么在年底统计商品的时候&#xff0c;这个商品要统计的&#xff0c;所以这个商品信息我们是不能删除的。 如果商城…