【数据结构手札】顺序表实战指南(二):结构体构建 | 初始化 | 打印 | 销毁

【数据结构手札】顺序表实战指南(二):结构体构建 | 初始化 | 打印 | 销毁
在这里插入图片描述


🌈个人主页:聆风吟
🔥系列专栏:数据结构手札
🔖少年有梦不应止于心动,更要付诸行动。


文章目录

📚专栏订阅推荐

专栏名称专栏简介
C++藏宝阁本专栏聚焦学习阶段核心知识点,深耕基础与实战,干货笔记持续更新,和大家共学共进,夯实编程功底。
数据结构手札本专栏主要是我的数据结构入门学习手札,记录个人从基础到进阶的学习总结。
数据结构手札・刷题篇本专栏是《数据结构手札》配套习题讲解,通过练习相关题目加深对算法理解。

📋前言 - 顺序表文章合集

-【顺序表(一):线性表定义 | 顺序表定义】

-【顺序表(二):初始化 | 打印 | 销毁】

-【顺序表(三):扩容 | 尾插 | 尾删】

-【顺序表(四):头插 | 头删】

-【顺序表(五):查找 | 任意位置增删】


一. ⛳️顺序表:重点回顾

1.1 🔔顺序表的定义

顺序表(Sequential List):用一段物理地址连续的存储单元依次存储数据元素的线性结构。一般情况下采用数组存储。在数组上完成数据的增删查改。

在这里插入图片描述



1.2 🔔顺序表的分类

顺序表一般可以分为:静态顺序表动态顺序表

1.2.1 👻静态顺序表

静态顺序表:指存储空间是固定的并且在程序运行前就已经确定大小的顺序表。它通常使用数组来实现,即通过定义一个固定长度的数组来存储数据元素。

静态顺序表的结构定义:

//静态顺序表结构定义#defineMAXSIZE7//存储单元初始分配量typedefint SLDataType;//类型重命名,便于统一修改元素类型typedefstructSeqList{ SLDataType data[MAXSIZE];//定长数组int size;//当前有效数据的个数}SeqList;

我们可以发现描述静态顺序表需要三个属性:

  • 存储空间的起始位置:数组data,他的存储位置就是存储空间的存储位置;
  • 线性表的最大存储容量:数组长MAXSIZE
  • 线性表的当前位置:size
在这里插入图片描述



1.2.2 👻动态顺序表

动态顺序表:通过动态分配内存空间,实现随着数据量的增加而不断扩容的效果。它的结构类似于一个数组,数据元素的存储是连续的,支持随机访问和顺序访问。

动态顺序表的结构定义:

//动态顺序表结构定义typedefint SLDataType;//类型重命名,便于统一修改元素类型typedefstructSeqList{ SLDataType* a;//指向动态开辟的数组int size;//当前有效数据的个数int capacity;//当前分配的总容量}SL;

我们可以发现描述动态顺序表也需要三个属性:

  • 存储空间的起始位置:指针a,他里面存储的地址就是存储空间的地址;
  • 线性表当前最大存储容量:capacity,可以通过动态分配的方式进行扩容;
  • 线性表的当前位置:size
在这里插入图片描述

二. ⛳️顺序表的基本操作实现

通过上期学习,我们已经了解了动态顺序表可以使程序更加高效和灵活,可以根据实际数据量动态地调整表的大小,避免在创建静态顺序表时浪费内存空间或者当数据量超出静态顺序表容量时造成数据丢失或程序崩溃等问题。因此,本文将采用动态顺序表结合图文去实现顺序表的一些基本操作。

2.1 🔔动态顺序表结构体构建

//动态顺序表#defineSLCAPACITY4typedefint SLDataType;typedefstructSeqList{ SLDataType* a;//指向动态开辟的数组int size;//有效数据的个数int capacity;//记录容量的空间大小}SL;

代码深剖:

  • 结构体中 a 指向的数组类型是我们重定义的SLDataType,这样当我们想创建其它类型的顺序表时只需要对 typedef 后面的数据类型int进行需改即可;
  • size是用来计数的,统计当前顺序表一共有多少个有效元素;
  • capacity是用来表示当前顺序表的容量,当size==capacity时说明当前顺序表已经“装满了”,需要扩容;
  • 定义标识符SLCAPACITY作为宏常量,用于指定顺序表初始化时的初始容量。便于将初始容量的值 “集中管理”,后续如果需要调整顺序表的初始容量(比如想把默认 4 个空间改成 8 个),无需在初始化函数的代码里逐个修改数值,只需修改INIT_CAPACITY的定义即可,既减少了代码出错的概率,也让程序的可维护性大大提升。

2.2 🔔初始化顺序表

//初始化顺序表voidSLInit(SL* ps){assert(ps);//使用malloc开辟空间 ps->a =(SLDataType*)malloc(sizeof(SLDataType)* SLCAPACITY);//判断空间是否开辟成功if(NULL== ps->a){//打印错误原因(比如 “malloc failed: Out of memory”),方便定位问题;perror("malloc failed");//终止程序并返回非 0 状态码(约定俗成表示程序异常退出),避免后续无效操作。exit(-1);}//初始化顺序表的有效元素个数为 0。 ps->size =0;//记录顺序表当前的最大容量。 ps->capacity = SLCAPACITY;}

代码深剖:

  • assert(ps);主要用于校验传入的顺序表指针是否有效(非空)。assert是断言宏,若psNULL(空指针),程序会直接终止并提示断言失败。因为后续所有操作都基于ps指向的顺序表结构体,如果传入空指针,操作ps->aps->size等会导致程序崩溃,这是防御性编程的核心手段,提前规避空指针访问的致命错误。(后文在出现就不多做叙述了)。
  • 使用malloc开辟空间,一定要进行判断是否开辟成功。因为malloc申请内存失败时(比如系统剩余内存不足)会返回NULL,若直接使用NULL指针操作数组,会触发 “段错误” 导致程序崩溃;

时间复杂度:

该程序没有循环,根据大O阶的推导方法很容易得出:初始化顺序表的时间复杂度为O(1)

2.3 🔔销毁顺序表

//销毁顺序表voidSLDestroy(SL* ps){assert(ps);//释放顺序表底层数组占用的动态内存。free(ps->a);//将指针置空,避免 “野指针” 问题。 ps->a =NULL;//重置顺序表的状态变量,让其回归 “初始无效状态”。 ps->size = ps->capacity =0;}

代码深剖:
为什么必须调用销毁函数?因为我们实现的是动态顺序表,其底层数组a指向的内存是通过malloc向操作系统 “临时申请” 的 —— 系统不会自动回收这块内存,如果使用后忘记释放,会造成内存泄漏:轻则持续占用系统资源,导致程序运行越久越卡顿;重则内存被耗尽,引发程序崩溃甚至系统异常。
时间复杂度:

该程序没有循环,根据大O阶的推导方法很容易得出:销毁顺序表的时间复杂度为O(1)

2.4 🔔打印顺序表

//打印顺序表voidSLPrint(SL* ps){assert(ps);for(int i =0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");}

代码深剖:
打印顺序表就是进行简单的遍历循环,此处不多做叙述。

时间复杂度:

该程序有单层循环,根据大O阶的推导方法很容易得出:打印顺序表的时间复杂度为O(n)

三. ⛳️顺序表的源代码

3.1 🔔SeqList.h 顺序表的函数声明

#include<stdio.h>#include<stdlib.h>#include<assert.h>//动态顺序表#defineSLCAPACITY4typedefint SLDataType;typedefstructSeqList{ SLDataType* a;//指向动态开辟的数组int size;//有效数据的个数int capacity;//记录容量的空间大小}SL;//初始化voidSLInit(SL* ps);//销毁顺序表voidSLDestroy(SL* ps);//打印顺序表voidSLPrint(SL* ps);

3.2 🔔SeqList.c 顺序表的函数定义

#include"SeqList.h"//初始化顺序表voidSLInit(SL* ps){assert(ps);//使用malloc开辟空间 ps->a =(SLDataType*)malloc(sizeof(SLDataType)* SLCAPACITY);//判断空间是否开辟成功if(NULL== ps->a){//打印错误原因(比如 “malloc failed: Out of memory”),方便定位问题;perror("malloc failed");//终止程序并返回非 0 状态码(约定俗成表示程序异常退出),避免后续无效操作。exit(-1);}//初始化顺序表的有效元素个数为 0。 ps->size =0;//记录顺序表当前的最大容量。 ps->capacity = SLCAPACITY;}//销毁顺序表voidSLDestroy(SL* ps){assert(ps);//释放顺序表底层数组占用的动态内存。free(ps->a);//将指针置空,避免 “野指针” 问题。 ps->a =NULL;//重置顺序表的状态变量,让其回归 “初始无效状态”。 ps->size = ps->capacity =0;}//打印顺序表voidSLPrint(SL* ps){assert(ps);for(int i =0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");}

3.3 🔔test.c 顺序表功能测试

#include"SeqList.h"intmain(){ SL sl;//初始化顺序表SLInit(&sl);printf("初始化后的顺序表状态:\n");printf("size = %d, capacity = %d\n", sl.size, sl.capacity);//还没有学习插入操作,在这里手动设置一些数据用于测试打印//不能超过4个,因为我们初始化只申请了四个数据的空间 sl.a[0]=10; sl.a[1]=20; sl.a[2]=30; sl.size =3;//有效数据个数SLPrint(&sl);//销毁顺序表SLDestroy(&sl);return0;}

📝全文总结

本文重点讲解动态顺序表的结构体构建,并实现了初始化打印销毁三大基础操作,明确了每个步骤的核心逻辑与注意事项,为后续学习顺序表的增删查改等进阶操作奠定了坚实基础。

今天的干货分享到这里就结束啦!如果觉得文章还可以的话,希望能给个三连支持一下,聆风吟的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的最大动力!

在这里插入图片描述

Read more

GitHub 上开源了 30+ 个 OpenClaw 真实使用案例。

最近逛 GitHub 的时候发现了一个挺有意思的仓库,专门收集 OpenClaw 的 usecases。 说实话,很多人装完 OpenClaw 之后的操作都是一样的:疯狂往里面塞各种 Skill,ClawHub 逛得跟菜市场一样热闹,今天装个天气查询,明天装个股票分析,后天又来个翻译助手。 结果装了一堆却发现每天还是在信息搜索、做个记录。Skill 装了一百个,生活一点没变轻松。 这个开源项目就是专门收集人们真实在用的 OpenClaw 场景,而不是单纯介绍某个 Skill 或插件。 01 开源项目简介 awesome-openclaw-usecases 目前收录了 30 多个经过验证的真实使用场景。 它的核心理念非常简单:不是教你装什么 Skill,而是告诉你别人是怎么把 OpenClaw 变成真正能帮人类干活的私人助理的。 如果你不知道 OpenClaw 具体能做什么,只停留在抽象概念。有一些自动化或搭建 AI 智能体想法,但不知道如何系统落地,想参考别人已经跑通的真实工作流和自动化方案。

By Ne0inhk
深度盘点:GitHub 上十大必装 Claude Skill,让你的 AI 助手效率提升 4 倍

深度盘点:GitHub 上十大必装 Claude Skill,让你的 AI 助手效率提升 4 倍

深度盘点:GitHub 上十大必装 Claude Skill,让你的 AI 助手效率提升 4 倍 Claude Code 已经很强大,但如果搭配这些精心设计的 Skills,它将变身超级生产力工具。本文为你深度解析 GitHub 上最受欢迎的 10 大 Claude Skills,帮助你找到最适合的配置方案。 引言:为什么 Claude Skills 如此重要? 在 2025-2026 年,Claude Code 生态经历了爆发式增长。Skills 系统的出现,让 Claude 从一个"对话助手"升级为"专业工具"。通过安装不同的 Skills,你可以:

By Ne0inhk
从安装到代码提交:Git 远程协作中 90% 的问题都能在这里找到答案

从安装到代码提交:Git 远程协作中 90% 的问题都能在这里找到答案

工欲善其事,必先利其器。 目录 * 安装 Git 的步骤: * 本地Git与远程仓库连接及操作全指南 * 一、本地仓库初始化与远程仓库连接 * 1. 初始化本地Git仓库 * 2. 关联远程仓库 * 1. 查看当前分支状态 * 2. 新建本地分支 * 方法1:基于当前分支创建新分支 * 方法2:创建并直接切换到新分支(推荐) * 方法3:基于远程分支创建本地分支 * 3. 切换到已有的本地分支 * 二、分支管理与远程分支同步 * 1. 查看远程分支 * 2. 拉取远程分支到本地 * 三、代码提交与推送到远程仓库 * 1. 常规提交流程 * 2. 简化推送命令 * 四、远程仓库信息查看与更新 * 1. 查看远程仓库详细信息 * 2. 同步远程仓库最新数据 * 五、常见问题解决与优化配置 * 1. 网络与连接问题修复 * 2. 推送大文件或提升传输稳定性

By Ne0inhk
2025电赛E题开源:二维云台激光打靶系统全解析(基于STM32F407+K230)

2025电赛E题开源:二维云台激光打靶系统全解析(基于STM32F407+K230)

2025电赛E题:二维云台激光打靶系统全解析——基于STM32F407的视觉伺服控制 本文详细介绍2025年全国大学生电子设计竞赛E题《二维云台激光打靶系统》的完整实现方案。项目基于STM32F407微控制器,结合视觉追踪、PID控制、步进电机驱动等技术,实现高精度的激光自动瞄准与发射功能。 🎯 项目背景与意义 在自动化控制领域,视觉伺服系统是实现高精度定位与追踪的关键技术。本次分享的项目,源自 2025 年全国大学生电子设计竞赛的赛题,题目要求设计一套二维云台系统,需具备自动识别目标、控制激光精准命中的功能。 该项目历经多重挑战,最终斩获了广东省赛区的省一等奖。由于我在此次比赛中主要负责二维云台激光打靶系统的设计,因此仅针对 25 年电赛 e 题的瞄准模块部分进行解说,自动循迹小车的内容会略过。 这个项目的成功落地,既为电子设计竞赛提供了一套完整的参考方案,也为嵌入式视觉伺服系统的教学与研究提供了宝贵的实践案例。 📊 系统总体设计 系统架构图 二维云台激光打靶系统 ├── 感知层(视觉模块) │ ├── 摄像头采集 │ └── 目标坐标提取 ├── 控制层(主控板

By Ne0inhk