顺序表 -->增、删、查、改等详细操作
个人主页 流年如梦专栏 《C语言》 《数据结构》文章目录一.线性表二.顺序表2.1概念与结构2.2静态顺序表2.3动态顺序表2.3.1动态顺序表结构体2.3.2头文件声明 -- SeqList.h2.3.3源文件实现 -- SeqList.c2.3.3.1初始化2.3.3.2销毁2.3.3.3打印2.3.3.4扩容检查2.3.3.5尾插尾删2.3.3.6头插头删2.3.3.7指定位置插入与删除2.3.3.8查找2.3.4主函数 -- test.c总结动态顺序表⚠️易错点Ladies and gentlemen本篇文章先了解一下线性表和顺序表其中主要学习动态顺序表重点全程高能不容错过前言顺序表是数据结构中最基础、最常用的线性表结构它以一段物理连续的内存空间存储数据是数组的封装与升级。本篇文章会实现动态顺序表的初始化、增删查改、扩容、销毁等核心接口并通过测试代码验证功能为后续学习链表、栈、队列等数据结构打下扎实基础一.线性表线性表是n个具有相同特性的数据元素的有限序列是一种在实际中广泛使用的数据结构常见的线性表顺序表、链表、栈、队列、字符串等线性表又分为逻辑结构和物理结构其中逻辑结构-- 线性结构连续一条直线物理结构-- 不一定连续(物理储存通常是以数组顺序表和链式结构链表这两种方式)二.顺序表2.1概念与结构顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构一般情况下采用数组存储。顺序表和数组的区别数组-- 原生存储空间顺序表-- 对数组的封装实现增、删、改、查等完整接口可以理解为数组-- 基础原料顺序表-- 封装好的成品结构在基础原料的基础上2.2静态顺序表使用定长数组存储元素#defineN7typedefstructSeqList{SLDataType a[N];intsize;}SL;分析其中a[N]为定长数组size为有效数据个数但缺点是空间给少了不够用给多了造成空间浪费2.3动态顺序表2.3.1动态顺序表结构体动态顺序表按需申请、释放空间更灵活typedefstructSeqList{SLDataType*a;intsize;intcapacity;}SL;分析其中SLDataType* a为指向动态开辟的数组size为有效数据个数capacity为空间容量2.3.2头文件声明 -- SeqList.h参考代码如下#pragmaonce#define_CRT_SECURE_NO_WARNINGS#includestdio.h#includestdlib.h#includeassert.h//初始容量#defineINIT_CAPACITY4//顺序表存储的数据类型typedefintSLDataType;//SLDataType为int类型//动态顺序表结构体typedefstructSeqList{SLDataType*a;intsize;intcapacity;}SL;//初始化voidSLInit(SL*ps);//销毁voidSLDestroy(SL*ps);//打印voidSLPrint(SL*ps);//扩容判断voidSLCheckCapacity(SL*ps);//头部插入删除voidSLPushBack(SL*ps,SLDataType x);voidSLPopBack(SL*ps);//尾部插入删除voidSLPushFront(SL*ps,SLDataType x);voidSLPopFront(SL*ps);//指定位置之前插入数据voidSLInsert(SL*ps,intpos,SLDataType x);//指定位置之前删除数据voidSLErase(SL*ps,intpos);//查找intSLFind(SL*ps,SLDataType x);2.3.3源文件实现 -- SeqList.c2.3.3.1初始化对动态顺序表进行初始化voidSLInit(SL*ps){assert(ps);ps-aNULL;ps-size0;ps-capacity0;}分析把数组指针置空有效数据个数和容量都清0assert防止传进来空指针2.3.3.2销毁销毁动态顺序表释放内存voidSLDestroy(SL*ps){assert(ps);free(ps-a);ps-aNULL;ps-size0;ps-capacity0;}分析必须free掉动态开辟的数组避免内存泄漏指针置空、数据置0防止野指针2.3.3.3打印遍历打印顺序表中所有有效数据voidSLPrint(SL*ps){assert(ps);for(inti0;ips-size;i){printf(%d ,ps-a[i]);}printf(\n);}2.3.3.4扩容检查判断空间是否满了满了就扩容一般扩 2 倍没了再扩voidSLCheckCapacity(SL*ps){assert(ps);if(ps-sizeps-capacity){intnewCapacityps-capacity0?INIT_CAPACITY:ps-capacity*2;SLDataType*tmp(SLDataType*)realloc(ps-a,newCapacity*sizeof(SLDataType));if(tmpNULL){perror(realloc fail);return;}ps-atmp;ps-capacitynewCapacity;}}分析第一次扩容给INIT_CAPACITY4之后每次扩2倍用realloc更高效所有插入操作前都要调用它2.3.3.5尾插尾删尾插在顺序表最后插入一个数据voidSLPushBack(SL*ps,SLDataType x){assert(ps);SLCheckCapacity(ps);ps-a[ps-size]x;ps-size;}分析插入操作先检查扩容再把数据放到size位置时间复杂度为O(1)尾删删除顺序表最后一个数据voidSLPopBack(SL*ps){assert(ps);assert(ps-size0);ps-size--;}分析不用真正删除只需size--逻辑删除使用之前必须断言size0防止删空表导致程序崩溃2.3.3.6头插头删头插在顺序表最前面插入数据voidSLPushFront(SL*ps,SLDataType x){assert(ps);SLCheckCapacity(ps);for(intips-size;i0;i--){ps-a[i]ps-a[i-1];}ps-a[0]x;ps-size;}分析插入操作先检查扩容所有数据先向后挪一位再把数据放在下标为0的位置时间复杂度为O(N)效率低头删删除第一个数据voidSLPopFront(SL*ps){assert(ps);assert(ps-size0);for(inti0;ips-size-1;i){ps-a[i]ps-a[i1];}ps-size--;}分析后面所有数据向前覆盖时间复杂度为O(N)效率低2.3.3.7指定位置插入与删除插入在下标pos前插入数据xvoidSLInsert(SL*ps,intpos,SLDataType x){assert(ps);assert(pos0posps-size);SLCheckCapacity(ps);for(intips-size;ipos;i--){ps-a[i]ps-a[i-1];}ps-a[pos]x;ps-size;}分析pos位置及之后的数据整体后移必须检查pos合法性 --0 ≤ pos ≤ size删除删除下标pos位置的数据voidSLErase(SL*ps,intpos){assert(ps);assert(pos0posps-size);for(intipos;ips-size-1;i){ps-a[i]ps-a[i1];}ps-size--;}分析pos后面的数据整体前移覆盖并且注意pos范围为0 ≤ pos size2.3.3.8查找查找x找到返回下标没找到则返回-1intSLFind(SL*ps,SLDataType x){assert(ps);for(inti0;ips-size;i){if(ps-a[i]x){returni;}}return-1;}分析顺序遍历时间复杂度为O(N)常用于修改、删除前先定位位置2.3.4主函数 -- test.c参考代码如下#includeSeqList.hvoidTestSeqList(){SL sl;//初始化SLInit(sl);//尾插SLPushBack(sl,1);SLPushBack(sl,2);SLPushBack(sl,3);SLPushBack(sl,4);printf(尾插 1 2 3 4);SLPrint(sl);//头插SLPushFront(sl,0);printf(头插 0);SLPrint(sl);//指定位置插入SLInsert(sl,3,99);printf(在下标3插入99);SLPrint(sl);//查找intposSLFind(sl,3);if(pos!-1){printf(找到 3下标是%d\n,pos);}//删除指定位置SLErase(sl,3);printf(删除下标3);SLPrint(sl);//头删SLPopFront(sl);printf(头删);SLPrint(sl);//尾删SLPopBack(sl);printf(尾删);SLPrint(sl);//销毁SLDestroy(sl);printf(销毁成功\n);}intmain(){TestSeqList();//调用函数return0;}运行结果总结动态顺序表动态顺序表是对数组的封装用连续物理内存存储数据支持动态扩容结构包含三要素数据指针a、有效数据size、容量capacity核心操作尾插与尾删、头插与头删、指定位置插入删除、查找所有接口按模块化实现.h声明、.c实现、test.c测试扩容规则初始空间容量为4满了2倍扩容需要用realloc尾插尾删时间复杂度为O(1)头插头删、中间插入删除的时间复杂度为O(N)因为需要挪动数据⚠️易错点忘记断言assert空指针访问导致崩溃扩容判断错误未判断size capacity就扩容realloc直接赋值不用临时变量tmp接收易丢失数据插入或删除的循环方向或边界写错造成数据覆盖或越界不检查pos合法性插入删除越界空表执行删除size变负逻辑异常销毁后未置空NULLfree后不置NULL产生野指针扩容后不更新capacity导致容量逻辑混乱 关注我们一路同行从入门到大师慢慢沉淀、稳步成长❤️ 点赞鼓励原创让优质内容被更多人看见⭐ 收藏收好核心知识点与实战技巧需要时随时查阅 评论分享你的疑问或踩坑经历一起交流避坑、共同进步
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2563201.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!