详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改
目录
一、线性表
二、顺序表
2.1概念及结构
2.2接口实现
2.3动态顺序表的创建
2.3动态顺序表的初始化
2.3.1传值初始化
2.3.2传址初始化
2.4动态顺序表的清空
2.5动态顺序表的扩容
2.6动态顺序表内容的打印
三、动态顺序表的使用
3.1尾插尾删
3.1.1尾插
3.1.2尾删
3.2头插头删
3.2.1头插
3.2.2头删
3.3在pos位置插入x
3.4删除pos位置的值
3.5修改某个位置的值
四、完整代码
一、线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储。

二、顺序表
2.1概念及结构
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存
储。在数组上完成数据的增删查改。
顺序表一般分为:
静态顺序表:使用定长数组储存元素。
//静态顺序表
#define N 100
struct SeqList
{int a[N];//定长数组int size;//有效数据的个数
};

缺点:不是很灵活
动态顺序表:使用动态开辟的数组储存。

2.2接口实现
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空
间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间
大小,所以下面我们实现动态顺序表。
所谓动态其实指的这个结构体里的指针是动态内存开辟来的,是可变的,用的时候动态开辟,不够的话继续开辟,程序结束的时候释放。
2.3动态顺序表的创建
typedef int SLDatatype;//将int重命名为SLDatatype
typedef struct SeqList
{SLDatatype* a;//指向动态开辟的数组SLDatatype capacity;//容量SLDatatype size;//有效数据的个数}SL;//将结构体SeqList重命名为SL
2.3动态顺序表的初始化
2.3.1传值初始化
//传值初始化
void SLInit(SL s)
{s.a = NULL;s.size = 0;s.capacity = 0;
}
函数那个章节我们学过形参只是实参的临时拷贝,并没有实际作用,生命周期短,出了函数的作用域就会销毁,我们不考虑这种初始化方式。
2.3.2传址初始化
//传址初始化
void SLInit(SL* ps)
{ps->a = 0;ps->capacity = 0;ps->size = 0;
}
void SLInit(SL* ps)
{ps->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);//开辟了4个字节的空间if (ps->a == NULL){perror("malloc failed");exit(-1);}ps->capacity = 4;//开辟了空间就要给容量赋值ps->size = 0;
}
上面两种初始化方式都可以给予结构体成员变量赋值,但是我们使用第二种,因为第二种为我们开辟了空间。
2.4动态顺序表的清空
void SLDestr(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = 0;//内存释放,容量清零ps->size = 0;//内存释放,有效数据清零
}
2.5动态顺序表的扩容
void SLCheckcapacity(SL* ps)
{if (ps->size == ps->capacity){SLDatatype* tmp = (SLDatatype*)realloc(ps->a, ps->capacity * 2 *( sizeof(SLDatatype)));//扩容尾原来的倍数if (tmp == NULL)//判断是否扩容失败{perror("realloc failed");exit(-1);}ps->a = tmp;ps->capacity *= 2;//扩容后修改原来的容量}
}
这就是所谓的动态,当我们空间不够时,就需要开辟新的空间,使用realloc函数要注意是否开辟成功,定义一个中间指针,当开辟成功时将这个指针赋值给动态数组中的指针。
2.6动态顺序表内容的打印
void SLprint(SL* ps)
{int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
size为有效数据个数,使用循环打印其中的有效数据。
三、动态顺序表的使用
3.1尾插尾删
3.1.1尾插
void SLPushBack(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);//检查空间是否足够插入ps->a[ps->size] = x;//赋值ps->size++;//插入一个有效数据,有效数据个数加一
}
首先一定要检查规矩是否足够,根据上面开辟的空间,容量为4,有效数据为size为0,所以从第一个空间开始插入数据。
3.1.2尾删
//尾删
void SLPopBack(SL* ps)
{assert(ps->size > 0);//判断是否会造成越界if (ps->size == 0){return;}ps->size--;//删除一个数据,有效数据个数减一
}
插入数据后size的大小也会变化,数组中最后一个数字的下标刚好和size的大小一样我们只需要将size减1就行。
3.2头插头删
3.2.1头插
void SLPushFront(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);//检查空间是否足够int end = ps->size;while (end > 0){ps->a[end] = ps->a[end - 1];//将前一个数据后移动end--;}ps->a[0] = x;//将x赋给初始位置ps->size++;//加入一个数字,有效数据个数加1
}
老规矩一定要检查空间是否足够,头部插入数据我们只需要将原来的数据往后移动一格就将第一格的位置空出来,再将数值插入就行,插入一个数据,有效数据加1即可。
3.2.2头删
void SLPopFront(SL* ps)
{assert(ps->size > 0);//防止越界访问if (ps->size==0){return;}int begin = 0;while (begin < ps->size){ps->a[begin] = ps->a[begin+1];//将后一个数据往前移动begin++;}ps->size--;//减少一个数字,有效数据减1
}
这里的删除并不是真正意义上的删除,我们只需要将原来的数据往前移动一位使后一位的数据覆盖在前一位,这就做到了删除,顺便再将有效数据减1就行。
3.3在pos位置插入x
void SLInsert(SL* ps, int pos, int x)
{assert(pos >= 0 && pos <= ps->size);//防止越界访问SLCheckcapacity(ps);int end = ps->size;while (end >=pos){ps->a[end] = ps->a[end-1];//和头插的思想差不多,将数据后移end--;}ps->a[pos] = x;//将x赋值给pos位置ps->size++;//有效数据加1
}
我们可以这样理解:将pos看成初始位置,是不是就转化为头插了?按照头插的思想就可以完成在pos位置上插入x。
3.4删除pos位置的值
void SLErase(SL* ps, int pos)
{assert(pos >= 0 && pos <= ps->size);//防止越界访问SLCheckcapacity(ps);int begin = pos;while (begin < ps->size){ps->a[begin] = ps->a[begin + 1];//和头删的思想差不多,将数据前移begin++;}ps->size--;//有效数据减1
}
我们会发现3.4和3.5不仅可以做到某个位置值的插入和删除,也可以做到尾插尾删和头插头删。
3.5修改某个位置的值
void SLModify(SL* ps, SLDatatype pos, SLDatatype x)
{assert(pos >= 0 && pos < ps->size);//防止越界ps->a[pos] = x;
}
这样修改某个位置的值看起来是挺麻烦,但是是为了安全考虑。
四、完整代码
#define _CRT_SECURE_NO_WARNINGS 67
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//静态顺序表
//#define N 100
//struct SeqList
//{
// int a[N];//定长数组
// int size;//有效数据的个数
//};//动态顺序表//创建
typedef int SLDatatype;
typedef struct SeqList
{SLDatatype* a;//指向动态开辟的数组SLDatatype capacity;//容量SLDatatype size;//有效数据的个数}SL;
//传值初始化
//void SLInit(SL s)
//{
// s.a = NULL;
// s.size = 0;
// s.capacity = 0;
//}
//传址初始化
//void SLInit(SL* ps)
//{
// ps->a = 0;
// ps->capacity = 0;
// ps->size = 0;
//}
void SLInit(SL* ps)
{ps->a = (SLDatatype*)malloc(sizeof(SLDatatype) * 4);//开辟了4个字节的空间if (ps->a == NULL){perror("malloc failed");exit(-1);}ps->capacity = 4;ps->size = 0;
}
//清空
void SLDestr(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = 0;ps->size = 0;
}
//打印
void SLprint(SL* ps)
{int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
//检查容量
void SLCheckcapacity(SL* ps)
{if (ps->size == ps->capacity){SLDatatype* tmp = (SLDatatype*)realloc(ps->a, ps->capacity * 2 *( sizeof(SLDatatype)));//扩容尾原来的倍数if (tmp == NULL){perror("realloc failed");exit(-1);}ps->a = tmp;ps->capacity *= 2;}
}
//尾插
void SLPushBack(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);ps->a[ps->size] = x;ps->size++;
}
//尾删
void SLPopBack(SL* ps)
{assert(ps->size > 0);if (ps->size == 0){return;}ps->size--;
}
//头插
void SLPushFront(SL* ps, SLDatatype x)
{SLCheckcapacity(ps);int end = ps->size;while (end > 0){ps->a[end] = ps->a[end - 1];end--;}ps->a[0] = x;ps->size++;
}
//头删
void SLPopFront(SL* ps)
{assert(ps->size > 0);if (ps->size==0){return;}int begin = 0;while (begin < ps->size){ps->a[begin] = ps->a[begin+1];begin++;}ps->size--;
}
//在pos位置插入x
void SLInsert(SL* ps, int pos, int x)
{assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);int end = ps->size;while (end >=pos){ps->a[end] = ps->a[end-1];end--;}ps->a[pos] = x;ps->size++;
}
//删除pos位置的值
void SLErase(SL* ps, int pos)
{assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);int begin = pos;while (begin < ps->size){ps->a[begin] = ps->a[begin + 1];begin++;}ps->size--;
}
int SLFind(SL* ps, int x)
{int i = 0;for (i = 0; i < ps->size; i++){if (ps->a[i] == x)return i;}return -1;
}void SLModify(SL* ps, SLDatatype pos, SLDatatype x)
{assert(pos >= 0 && pos < ps->size);ps->a[pos] = x;
}
int main()
{SL s1;//传值初始化//SLInit(s1);//传址初始化SLInit(&s1);//尾插SLPushBack(&s1, 1);SLPushBack(&s1, 2);SLPushBack(&s1, 3);SLPushBack(&s1, 4);SLPushBack(&s1, 5);SLPushBack(&s1, 6);SLPushBack(&s1, 7);//尾插测试printf("尾插:\n");SLprint(&s1);//尾删SLPopBack(&s1);//尾删测试printf("尾删:\n");SLprint(&s1);//头插SLPushFront(&s1,10);//头插测试printf("头插:\n");SLprint(&s1);//头删 SLPopFront(&s1);//头删测试printf("头删:\n");SLprint(&s1);//在pos位置插入xSLInsert(&s1, 0, 100);//pos插入x测试printf("pos位置插入x\n");SLprint(&s1);//删除pos位置的值SLErase(&s1, 0);//测试printf("删除pos位置的值\n");SLprint(&s1);//改SLModify(&s1, 2, 1);printf("修改某个位置上的值:\n");//SLprint(&s1);//清空SLDestr(&s1);return 0;
}

相关文章:
详解初阶数据结构之顺序表(SeqList)——单文件文件实现SeqList的增删查改
目录 一、线性表 二、顺序表 2.1概念及结构 2.2接口实现 2.3动态顺序表的创建 2.3动态顺序表的初始化 2.3.1传值初始化 2.3.2传址初始化 2.4动态顺序表的清空 2.5动态顺序表的扩容 2.6动态顺序表内容的打印 三、动态顺序表的使用 3.1尾插尾删 3.1.1尾插 3.1.2尾删…...
JavaScript中的深拷贝和浅拷贝
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 浅拷贝(Shallow Copy):⭐深拷贝(Deep Copy):⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带…...
树形结构的节点作为查询参数业务
1、业务描述 有一个树结构,存在一个唯一的code和一个父节点的pcode,要求前端传入任意层的code匹配这个code对应的所有子节点对应的数据。 2、解决思路 因为无法判定传入的code到底在那层,so 直接递归调用查询判断,如果有子节点就…...
sql:SQL优化知识点记录(十二)
(1)读锁案例讲解 加读锁和写锁 查看是否上锁:In_use:变成了1 读写锁对我们数据产生哪些影响: 读锁:是共享锁,其他线程可以查看: 加了读锁:session1不能修改自己…...
一.使用qt creator 设计显示GUI
一.安装qt creator 二.创建项目 文件-》新建项目 三.使用设计 可以直接使用鼠标拖拽 四.转换为py文件 # from123.py 为导出 py文件的文件名 form.ui 为 qt creator创造的 ui 文件 pyuic5 -o x:\xxx\from123.py form.ui五.显示GUI from PyQt5.QtWidgets import * fr…...
sql:SQL优化知识点记录(八)
(1)索引面试题分析 所谓索引:就是排好序的快速查找数据结构,排序家查找是索引的两个用途 select * 在where使用到了索引,当select * 有模糊查询%在左边索引会失效 当select * where后面索引的顺序发生变化࿰…...
java笔试题,寻找多出来的元素
题目:有两个数组a和b,其中b有一个元素是a没有的,其他元素都相同,请找出b中这个多余的元素。 1 public class Test02 { 2 3 public static void main(String[] args) { 4 int[] a {11, 34, 9, -4, 100, 98}; 5 int[] b {34…...
docker笔记3 Docker常规安装
1.安装tomcat docker hub上面查找tomcat镜像 docker search tomcat 从docker hub上拉取tomcat镜像到本地 docker pull tomcat docker images查看是否有拉取到的tomcat 使用tomcat镜像创建容器实例(也叫运行镜像) docker run -it -p 8080:8080 tomcat -p 小写,主…...
阻止 NTLM后无法登录远程桌面的原因
阻止 NTLM(NT LAN Manager) 攻击设置二 之前郑州景安的服务器被攻击,没过几天阿里云的也被攻击,且都是 NTLM 攻击。 Operating System: Windows Server 2008(R2) Enterprise Service Pack 1 64bit 一、winr 输入 gpedit.msc 二、依次进入:…...
Docker网络功能
基本网络功能 Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。使用docker network子命令来管理Docker网络。 外部访问容器可通过端口映射实现,启动容器时使用-p参数指定映射关系。-p可多次使用来绑定多个端口。使用docker port命令查看当前映射的端…...
如何入门 AI----如何确定学习目标
当确定学习人工智能(AI)的目标时,可以考虑以下具体的步骤: 兴趣和好奇心: 首先,问问自己,您对哪些 AI 领域感兴趣?是机器学习、自然语言处理、计算机视觉,还是其他领域&a…...
ABAP中加前导零和去前导零方法
文章目录 1 Introduction2 Method 1 Introduction In the sap there are two method for leading zero. We can use function or use the below the method . 2 Method SELECT * INTO TABLE DATA(IT_ITEM)FROM MARA .LOOP AT IT_ITEM ASSIGNING FIELD-SYMBOL(<FS_DATA&g…...
聊聊ShardingSphere是怎么进行sql重写的
序 本文主要研究一下ShardingSphere进行sql重写的原理 prepareStatement org/apache/shardingsphere/driver/jdbc/core/connection/ShardingSphereConnection.java public final class ShardingSphereConnection extends AbstractConnectionAdapter {Overridepublic Prepar…...
软件设计模式系列之二——抽象工厂模式
1 抽象工厂模式的定义 抽象工厂模式是一种创建型设计模式,它提供了一种创建一组相关或相互依赖对象的方式,而无需指定它们的具体类。该模式以一组抽象接口为核心,包括抽象工厂接口和一组抽象产品接口,每个具体工厂类负责创建特定…...
P2719 搞笑世界杯 (期望dp
#include <bits/stdc.h> using namespace std; using VI vector<int>;double dp[2000][2000]; int n; //求dp[2][0] //dp[0][2] //期望dp要从终末态,向起始态转移 //dp[a][b] - > dp[a][b-1] or dp[a-1][b] //dp[a][b] 1/2 * dp[a][b1] 1/2 * dp…...
spring cloud新版本使用loadbalancer替代Ribbon
Nacos 2021 不再集成 Ribbon,建议使用spring cloud loadbalancer 引入 一、简单使用 引入依赖spring cloud loadbalancer <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer<…...
【Git-Exception】Git报错:fatal: unable to auto-detect email address
报错信息: *** Please tell me who you are. Run git config --global user.email “youexample.com” git config –global user.name “Your Name” to set your account’s default identity. Omit --global to set the identity only in this repository. fatal…...
JVM性能优化 —— 类加载器,手动实现类的热加载
一、类加载的机制的层次结构 每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑,这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件,”.class”文件中保存着Java代码经转换后的虚拟机指令,当需要使用某个类时&#…...
SSH连接MobaXterm
IT常用软件的安装 ssh连接MobaXterm详细使用教程 数据库Navicat安装:https://www.jianshu.com/p/2494e02caf63 java SE安装 https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html windows安装pip https://www.cnblogs.com/NanShan2016/…...
本地虚机Jumpserver使用域名访问报错 使用IP+端口没有错误
背景: 我在本地Windows VMware 15的环境中部署了CentOS7.5,下载jumpserver-offline-installer-v2.28.1-amd64-138.tar.gz并安装部署。 需求: 1、能使用http:ip访问堡垒机。达成; 2、能使用http:域名访问堡垒机。达成ÿ…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
