2026/4/18 6:23:24
网站建设
项目流程
大人和孩做爰网站,苏州制作手机网站,陕西整站关键词自然排名优化,psd设计网站模板#x1f308;个人主页#xff1a;聆风吟 #x1f525;系列专栏#xff1a;数据结构手札 #x1f516;少年有梦不应止于心动#xff0c;更要付诸行动。 文章目录#x1f4da;专栏订阅推荐#x1f4cb;前言 - 顺序表文章合集一. ⛳️顺序表#xff1a;重点回顾1.1 …个人主页聆风吟系列专栏数据结构手札少年有梦不应止于心动更要付诸行动。文章目录专栏订阅推荐前言 - 顺序表文章合集一. ⛳️顺序表重点回顾1.1 顺序表的定义1.2 顺序表的分类1.2.1 静态顺序表1.2.2 动态顺序表二. ⛳️顺序表的基本操作实现2.1 查找某个值的下标2.2 在下标为pos位置插入x2.3 删除下标为pos位置的数据三. ⛳️顺序表的源代码3.1 SeqList.h 顺序表的函数声明3.2 SeqList.c 顺序表的函数定义3.3 test.c 顺序表功能测试全文总结专栏订阅推荐专栏名称专栏简介数据结构手札本专栏主要是我的数据结构入门学习手札记录个人从基础到进阶的学习总结。数据结构手札・刷题篇本专栏是《数据结构手札》配套习题讲解通过练习相关题目加深对算法理解。前言 - 顺序表文章合集-【顺序表一线性表定义 | 顺序表定义】-【顺序表二初始化 | 打印 | 销毁】-【顺序表三扩容 | 尾插 | 尾删】-【顺序表四头插 | 头删】-【顺序表五查找 | 任意位置增删】后续文章会陆续补充尽情期待…一. ⛳️顺序表重点回顾1.1 顺序表的定义顺序表Sequential List用一段物理地址连续的存储单元依次存储数据元素的线性结构。一般情况下采用数组存储。在数组上完成数据的增删查改。1.2 顺序表的分类顺序表一般可以分为静态顺序表和动态顺序表。1.2.1 静态顺序表静态顺序表指存储空间是固定的并且在程序运行前就已经确定大小的顺序表。它通常使用数组来实现即通过定义一个固定长度的数组来存储数据元素。静态顺序表的结构定义//静态顺序表结构定义#defineMAXSIZE7//存储单元初始分配量typedefintSLDataType;//类型重命名便于统一修改元素类型typedefstructSeqList{SLDataType data[MAXSIZE];//定长数组intsize;//当前有效数据的个数}SeqList;我们可以发现描述静态顺序表需要三个属性存储空间的起始位置数组data他的存储位置就是存储空间的存储位置线性表的最大存储容量数组长MAXSIZE线性表的当前位置size。1.2.2 动态顺序表动态顺序表通过动态分配内存空间实现随着数据量的增加而不断扩容的效果。它的结构类似于一个数组数据元素的存储是连续的支持随机访问和顺序访问。动态顺序表的结构定义//动态顺序表结构定义typedefintSLDataType;//类型重命名便于统一修改元素类型typedefstructSeqList{SLDataType*a;//指向动态开辟的数组intsize;//当前有效数据的个数intcapacity;//当前分配的总容量}SL;我们可以发现描述动态顺序表也需要三个属性存储空间的起始位置指针a他里面存储的地址就是存储空间的地址线性表当前最大存储容量capacity可以通过动态分配的方式进行扩容线性表的当前位置size。二. ⛳️顺序表的基本操作实现通过前面的学习我们已掌握动态顺序表的初始化、打印、销毁等基础操作以及尾插 / 尾删、头插 / 头删等针对性插入删除操作。本文将讲解顺序表更通用的操作查找某个值的下标、在下标为 pos 位置插入 x、删除下标为 pos 位置的数据实现任意位置的精准操作。2.1 查找某个值的下标查找某个值的下标是顺序表的基础查询操作核心逻辑是遍历顺序表的所有有效元素逐一比对元素值与目标值找到匹配项时返回其下标若遍历结束仍未找到则返回约定的 “无效标识”如 - 1。该操作为后续 “指定位置插入 / 删除” 的前置基础 —— 只有先找到目标元素的位置才能精准执行插入或删除操作。//查找某个值的下标,没找到返回-1intSLFind(SL*ps,SLDataType x){//检查顺序表指针有效性assert(ps);//遍历所有有效元素for(inti0;ips-size;i){//找到匹配值立即返回对应下标if(ps-a[i]x)returni;}//遍历结束未找到返回-1或无效下标标识return-1;}时间复杂度查找操作需遍历顺序表的有效元素最坏情况下目标值不存在或在最后一个位置需遍历n个元素n为有效元素个数因此时间复杂度为O(n)。2.2 在下标为pos位置插入x在下标为pos的位置插入元素x是顺序表插入操作的通用形式头插是pos0的特例尾插是possize的特例。核心逻辑是先校验插入位置的合法性再确保容量充足接着将pos位置及之后的所有元素向后挪动一位为新元素x腾出pos位置最后完成插入并更新有效元素个数。整体思路图解//在下标为pos的位置插入xvoidSLInsert(SL*ps,intpos,SLDataType x){//检查顺序表指针有效性assert(ps);//检查pos是否在有效范围内assert(pos0posps-size);//检查是否需要扩容保证有空间存放新元素SLCheckCapacity(ps);//挪动数据从最后一个有效元素开始到pos位置结束intendps-size-1;while(endpos){//当前元素向后挪一位ps-a[end1]ps-a[end];//向前移动处理前一个元素--end;}//插入元素pos位置已空闲直接赋值ps-a[pos]x;//更新有效元素个数ps-size;}时间复杂度pos位置插入的时间复杂度取决于需要挪动的元素个数最优情况possize尾插无需挪动元素时间复杂度O(1)最坏情况pos0头插需挪动所有n个元素时间复杂度O(n)大 O 阶推导中取最坏情况因此整体时间复杂度为O(n)n为有效元素个数。2.3 删除下标为pos位置的数据删除下标为pos位置的数据是顺序表删除操作的通用形式头删是pos0的特例尾删可看作possize-1的特例。核心逻辑是先校验删除位置的合法性再将pos1位置到最后一个有效元素的所有元素向前挪动一位覆盖被删除的pos位置元素最后通过size--完成逻辑删除。整体思路图解//删除下标为pos位置的数据voidSLErase(SL*ps,intpos){//检查顺序表指针有效性assert(ps);//检查pos是否在有效范围内0 ≤ pos size仅允许删除有效元素assert(pos0posps-size);//挪动元素向前覆盖从pos1位置开始到最后一个元素结束intbeginpos1;while(beginps-size){//当前元素向前挪一位覆盖被删除位置ps-a[begin-1]ps-a[begin];//向后移动处理下一个元素begin;}ps-size--;//更新有效元素个数}时间复杂度pos 位置删除的时间复杂度取决于需要挪动的元素个数最优情况possize-1尾删无需挪动元素时间复杂度O(1)最坏情况pos0头删需挪动所有n-1个元素时间复杂度O(n)大 O 阶推导中取最坏情况因此整体时间复杂度为O(n)n为有效元素个数。三. ⛳️顺序表的源代码3.1 SeqList.h 顺序表的函数声明#includestdio.h#includestdlib.h#includeassert.h//动态顺序表#defineSLCAPACITY4typedefintSLDataType;typedefstructSeqList{SLDataType*a;//指向动态开辟的数组intsize;//有效数据的个数intcapacity;//记录容量的空间大小}SL;//******************** 本文最新学习内容 ********************//查找某个值的下标,没找到返回-1intSLFind(SL*ps,SLDataType x);//在pos位置插入xvoidSLInsert(SL*ps,intpos,SLDataType x);//删除pos位置的数据voidSLErase(SL*ps,intpos);//******************** 前面已学习内容可能会调用 ********************//初始化voidSLInit(SL*ps);//销毁顺序表voidSLDestroy(SL*ps);//打印顺序表voidSLPrint(SL*ps);//检查容量是否够不够进行扩容voidSLCheckCapacity(SL*ps);//尾插voidSLPushBack(SL*ps,SLDataType x);3.2 SeqList.c 顺序表的函数定义#includeSeqList.h//******************** 本文最新学习内容 ********************//查找某个值的下标,没找到返回-1intSLFind(SL*ps,SLDataType x){//检查顺序表指针有效性assert(ps);//遍历所有有效元素for(inti0;ips-size;i){//找到匹配值立即返回对应下标if(ps-a[i]x)returni;}//遍历结束未找到返回-1或无效下标标识return-1;}//在下标为pos的位置插入xvoidSLInsert(SL*ps,intpos,SLDataType x){//检查顺序表指针有效性assert(ps);//检查pos是否在有效范围内assert(pos0posps-size);//检查是否需要扩容保证有空间存放新元素SLCheckCapacity(ps);//挪动数据从最后一个有效元素开始到pos位置结束intendps-size-1;while(endpos){//当前元素向后挪一位ps-a[end1]ps-a[end];//向前移动处理前一个元素--end;}//插入元素pos位置已空闲直接赋值ps-a[pos]x;//更新有效元素个数ps-size;}//删除下标为pos位置的数据voidSLErase(SL*ps,intpos){//检查顺序表指针有效性assert(ps);//检查pos是否在有效范围内0 ≤ pos size仅允许删除有效元素assert(pos0posps-size);//挪动元素向前覆盖从pos1位置开始到最后一个元素结束intbeginpos1;while(beginps-size){//当前元素向前挪一位覆盖被删除位置ps-a[begin-1]ps-a[begin];//向后移动处理下一个元素begin;}ps-size--;//更新有效元素个数}//******************** 前面已学习内容可能会调用 ********************//初始化顺序表voidSLInit(SL*ps){assert(ps);//使用malloc开辟空间ps-a(SLDataType*)malloc(sizeof(SLDataType)*SLCAPACITY);//判断空间是否开辟成功if(NULLps-a){//打印错误原因比如 “malloc failed: Out of memory”方便定位问题perror(malloc failed);//终止程序并返回非 0 状态码约定俗成表示程序异常退出避免后续无效操作。exit(-1);}//初始化顺序表的有效元素个数为 0。ps-size0;//记录顺序表当前的最大容量。ps-capacitySLCAPACITY;}//销毁顺序表voidSLDestroy(SL*ps){assert(ps);//释放顺序表底层数组占用的动态内存。free(ps-a);//将指针置空避免 “野指针” 问题。ps-aNULL;//重置顺序表的状态变量让其回归 “初始无效状态”。ps-sizeps-capacity0;}//打印顺序表voidSLPrint(SL*ps){assert(ps);for(inti0;ips-size;i){printf(%d ,ps-a[i]);}printf(\n);}//检查容量是否够不够进行扩容voidSLCheckCapacity(SL*ps){//断言检查指针有效性assert(ps);//判断是否需要扩容if(ps-sizeps-capacity){//使用realloc进行扩容SLDataType*temp(SLDataType*)realloc(ps-a,sizeof(SLDataType)*2*(ps-capacity));//检查是否扩容成功if(tempNULL){perror(realloc failed);//打印错误原因如内存不足exit(-1);//终止程序避免后续非法操作}ps-atemp;//更新数组指针ps-capacity*2;//更新容量值}}//尾插voidSLPushBack(SL*ps,SLDataType x){//断言检查指针有效性assert(ps);//检查是否需要扩容SLCheckCapacity(ps);ps-a[ps-size]x;//尾插核心操作赋值ps-size;//更新已用元素个数}3.3 test.c 顺序表功能测试#includeSeqList.hintmain(){SL sl;//初始化顺序表前面已经讲过本文不做过多叙述SLInit(sl);//尾插前面已经讲过本文用于添加测试数据仅为测试本文函数做铺垫SLPushBack(sl,10);SLPushBack(sl,20);SLPushBack(sl,30);SLPushBack(sl,40);printf(初始顺序表);//打印顺序表前面已经讲过本文不做过多叙述SLPrint(sl);// 输出10 20 30 40printf(\n);printf(******************** 测试1查找某个值的下标 ********************\n);//测试1查找某个值的下标intfindPosSLFind(sl,30);printf(查找值30的下标%d\n,findPos);//输出2intfindPosNoneSLFind(sl,50);printf(查找值50的下标不存在%d\n,findPosNone);//输出-1printf(\n);printf(******************** 测试2在下标pos位置插入x ********************\n);//测试2在下标pos位置插入xSLInsert(sl,2,25);//在下标2插入25printf(下标2的位置插入25后);SLPrint(sl);//输出10 20 25 30 40printf(\n);printf(******************** 测试3删除下标pos位置的数据 ********************\n);//测试3删除下标pos位置的数据SLErase(sl,2);//删除下标2的25printf(删除下标为2的数据后);SLPrint(sl);//输出10 20 30 40printf(\n);//销毁顺序表前面已经讲过本文不做过多叙述SLDestroy(sl);return0;}代码运行图全文总结本文重点讲解顺序表的查找某个值的下标、在下标为 pos 位置插入 x、删除下标为 pos 位置的数据三大基础操作。通过这些操作我们可实现顺序表的精准查询与任意位置的增删进一步完善了顺序表的核心功能。今天的干货分享到这里就结束啦如果觉得文章还可以的话希望能给个三连支持一下聆风吟的主页还有很多有趣的文章欢迎小伙伴们前去点评您的支持就是作者前进的最大动力