当前位置: 首页 > news >正文

顺序表的动态分配

文章目录

  • 代码
    • 代码解读
      • 类型定义
      • InitList ()含义
      • IncreaseSize()含义
        • 流程
        • 规范说明
    • 注意

代码

#include<stdlib.h>#defineInitSize10//默认的最大长度typedefstruct{int*data;// 指示动态分配数组的首地址intMaxSize;// 顺序表的最大容量intlength;// 顺序表的当前有效长度}SeqList;// 顺序表的类型定义// 初始化动态顺序表voidInitList(SeqList&L){// malloc申请连续堆内存L.data=(int*)malloc(InitSize*sizeof(int));L.length=0;L.MaxSize=InitSize;}// 扩容函数:增加动态数组的长度voidIncreaseSize(SeqList&L,intlen){int*p=L.data;// 先保存旧数组首地址// 开辟更大的新空间L.data=(int*)malloc((L.MaxSize+len)*sizeof(int));// 把旧数据拷贝到新空间for(inti=0;i<L.length;i++){L.data[i]=p[i];}L.MaxSize=L.MaxSize+len;// 更新最大容量free(p);// 释放旧数组内存,防止内存泄漏}intmain(){SeqList L;// 栈上创建顺序表结构体InitList(L);// 初始化IncreaseSize(L,5);// 扩容5个int空间return0;}
  • 和静态顺序表核心区别
    静态:int data[MaxSize]数组空间固定在栈,无法扩容;
    动态:int *data 空间在堆,可重新 malloc 扩容。

代码解读

类型定义

结构体里存的是指向堆中动态分配的数组,不是固定数组;(相当于是一张“门牌号纸条”)

typedefstruct{int*data;// ① 这是一个指针变量,将来存放堆区数组的起始地址intMaxSize;// ② 记录当前总共分配了多少个坑位(容量)intlength;// ③ 记录当前实际用了多少个坑位(有效长度)}SeqList;

栈区 (Stack):SeqList L
[ data ] = 0x1000 (指向堆区的门牌号)
[ MaxSize ] = 10
[ length ] = 0
堆区 (Heap):
地址 0x1000 → [ 坑0 ][ 坑1 ] … [ 坑9 ] (共 10 个 int,40 字节)

InitList ()含义

可以理解为:在堆区“盖房子”,把门牌号写在便利贴上

voidInitList(SeqList&L){// L 是 SeqList 类型变量,L.data 就是访问这个自定义成员。L.data=(int*)malloc(InitSize*sizeof(int));L.length=0;L.MaxSize=InitSize;}
  • malloc(InitSize * sizeof(int)):向操作系统申请10 * 4 = 40字节的连续堆内存。假设返回的起始地址是 0x1000。
  • (int *)强制转换:告诉编译器,“这块地以后要按 int 的步长(4字节)来切割”。
  • L.data = ...:把 0x1000 这个门牌号,复制到结构体 L 的 data 这个格子中。
    • ** 作用:在堆内存开辟一块能存InitSizeint连续空间,返回首地址赋值给L.data**
  • L.length = 0; L.MaxSize = 10;:设置当前有效个数为 0(空表),记录总容量为 10。

IncreaseSize()含义

这是整段代码的灵魂操作。当MaxSize不够用时,C 语言没有像 JS 那样的自动扩容,必须手动实现“找新家、搬家具、拆旧房”。

voidIncreaseSize(SeqList&L,intlen){int*p=L.data;// 步骤1L.data=(int*)malloc((L.MaxSize+len)*sizeof(int));// 步骤2for(inti=0;i<L.length;i++){L.data[i]=p[i];// 步骤3}L.MaxSize=L.MaxSize+len;// 步骤4free(p);// 步骤5}
流程
步骤代码物理内存行为通俗类比解释
int *p = L.data;临时新建一张便利贴 p,把原来的门牌号 0x1000 抄下来。(假设的动态数组首地址)在旧房子被推倒前,先拿手机拍下门牌号。
L.data = malloc((MaxSize+len)*sizeof(int));在堆区另找一块更大的地皮(比如 0x2000),把新门牌号 0x2000 写入 L.data。找搬家公司,在别处租了更大的新房子。
for… L.data[i]=p[i];挨个访问旧地址 0x1000 + i4 读取数据,写入新地址 0x2000 + i4。把旧房子里的家具一件件搬到新房子。
L.MaxSize = L.MaxSize + len;把容量记录从 10 更新为 15。房产证上更新新家的面积。
free(p);把地址 0x1000 的 40 字节彻底归还给操作系统。旧房子产权注销,彻底拆掉。
规范说明
  1. 备份旧数组地址int *p = L.data;
    一旦给L.data赋新地址,旧内存地址会丢失,无法释放,造成内存泄漏;
  2. 开辟更大的新堆空间总容量 = 原有 MaxSize + 新增 len;
  3. 循环拷贝所有有效数据只复制0~length-1有效元素,垃圾值不用复制;
  4. 更新最大容量L.MaxSize = L.MaxSize + len;
  5. free 释放旧数组:必须写 free。
  • 为什么必须有第⑤步(极重要)
    如果不写free(p),旧的 40 字节内存就永远被占着,且由于 L.data 已经指向了 0x2000,再也找不到 0x1000 的门牌号(首地址)了。这就造成了内存泄漏

注意

代码中需要提示的是:L 是 SeqList 类型变量,L.data 就是访问这个自定义成员。

http://www.cnnetsun.cn/news/3380261.html

相关文章:

  • 从零构建日本麻将AI:融合概率计算与强化学习的智能决策引擎
  • LangGraph智能体开发:流式输出与状态管理实战
  • Java 并发编程(七)|JUC 工具类与线程安全集合考点
  • 柯尔嫚模式系统小程序开发
  • 如何高效使用幻兽帕鲁存档修复工具:跨服务器迁移的完整实战指南
  • 【机器学习实战】高斯混合模型(GMM):从数学推导到Python代码实现
  • 从参数手册到电路实战:稳压二极管选型的关键步骤与避坑指南
  • 全产业链标准化体系、经济测算与政策落地路径
  • Codex 进阶教程:Skills、Memories、AGENTS.md、MCP、Automations 与 SDK 全解(2026 版)
  • 同一个AI别再硬扛所有任务:GPT 5.6 Luna、Terra、Sol三模型实战选择指南
  • 我用GPT 5.6组了一支AI虚拟团队:从需求混乱到内容、代码、知识库协同落地
  • 前端表格隔行换色功能制作指南:从原理到实战
  • 开源大模型微调技术与生产部署实战指南
  • 基于Python与Django的旅游景点数据可视化分析平台设计与实现
  • 警惕!ChatGPT行业正经历“伪智能泡沫”破裂期:3个真实崩盘案例+4个避险信号识别指南
  • AD5593R与PIC18F66K40硬件协同设计与优化实践
  • 半小时落地企业官网:OpenClaw2.7.9 AI 建站完整实操流程(含安装包)
  • 【蓝牙精品系列文档】【03_blemesh架构】02_网络层
  • 获奖平台传播易 全域广告投放一站式解决方案
  • 物联网安全芯片SE050与PIC18F4682的硬件集成方案
  • 软件设计师冲刺:核心考点速记与实战联想
  • TMC7300与PIC24EP512GU814电机控制方案详解
  • LangChain 学习记录 03:提示词模板 PromptTemplate 与 ChatPromptTemplate 详解
  • ChatGPT实体识别从零到上线:手把手教会你构建高准确率NER流水线(F1≥92.6%实测验证)
  • Mac钥匙串访问:管理与同步已保存Wi-Fi密码的进阶指南
  • 收藏必备!小白程序员也能快速上手学习大模型,打造智能病历生成神器
  • 大模型微调实战:从LoRA到QLoRA的完整流程与避坑指南
  • 多智能体强化学习与生物智能融合的技术探索
  • 内容7 内存管理 1​​
  • pandas字符串操作太慢?用Polars和PyArrow提速20倍实战指南