动态数组:编程世界的伸缩魔术(程序员必看干货!)

深入浅出Java ArrayList:动态数组的灵活之道 ArrayList作为Java集合框架的基石,其设计体现了空间换时间的经典思想。通过理解它的动态扩容机制、时间复杂度特性以及线程安全问题,我们能在实际开发中做出更明智的选择。就像选择交通工具:ArrayList是"空间宽敞但需要定期加油的SUV",LinkedList是"穿街走巷灵活的摩托车",而Vector则是"笨重但结实的装甲车"。理解它们的特性,才能为不同场景选择最合适的工具。记住这个黄金法则数据量有多大?主要操作是什么?(查询/增删)是否需要线程安全? 阅读详情

一、当数组遇上"成长烦恼"

刚学编程那会儿,老师教我们用数组存数据。当时觉得这玩意儿真方便,直到某天我要记录全校学生的考试成绩…(当场傻眼)

普通数组就像固定大小的收纳盒,初始化时就必须确定容量。比如int scores[500],万一学生增加到501人?不好意思,程序直接崩溃给你看!这种场景下,动态数组就像会变魔术的百宝箱,需要多少空间就自动扩展多少,简直不要太贴心!

二、动态数组的"超能力"揭秘

1. 扩容的魔法原理

动态数组内部其实暗藏玄机:

  1. 初始分配基础容量(比如10个位置)
  2. 当空间不够时,偷偷做三件事:
    • 创建更大的新数组(通常翻倍)
    • 把旧数据搬过去
    • 销毁旧数组(深藏功与名)

这个过程就像搬家:小房子住不下了,就换个大house,但地址门牌号(引用)保持不变!(是不是很神奇?)

2. 时间复杂度那些事儿

虽然动态数组能自动扩容,但频繁扩容会影响性能。这里有个摊还分析的概念:虽然单次扩容是O(n),但平均到每次插入操作,时间复杂度仍是O(1)!

举个栗子🌰:假设每次扩容都翻倍

容量变化:1 → 2 → 4 → 8 → 16...
复制次数:1 + 2 + 4 + 8... ≈ 2n

所以平均到每个元素,复制次数≈2次(数学不好的同学记住结论就行)

三、不同语言的实现姿势

1. Java的ArrayList(打工人的最爱)

ArrayList<String> playlist = new ArrayList<>();
playlist.add("周杰伦-晴天");  // 自动扩容
playlist.remove(0);          // 自动缩容
playlist.trimToSize();       // 手动瘦身(强迫症专用)

2. Python的List(动态数组本尊)

fruits = []
fruits.append("🍎")  # 自动扩容
fruits.pop()        # 自动缩容
print(fruits)       # 输出:[]

3. C++的vector(性能怪兽)

#include <vector>
std::vector<int> primes;
primes.reserve(100);  // 预分配空间(老司机操作)
primes.push_back(2);
primes.shrink_to_fit(); // 释放多余空间

四、实战中的避坑指南

1. 预分配空间(重要!)

如果知道大概的数据量,提前设置初始容量能避免多次扩容。比如Java中:

// 错误示范 ❌
List<Student> classA = new ArrayList<>(); 

// 正确姿势 ✅
List<Student> classA = new ArrayList<>(60); // 预计60个学生

2. 遍历时的删除操作

动态数组在遍历时修改会引发ConcurrentModificationException(Java党懂的都懂),解决方案:

// 错误写法 ❌
for(Student s : students) {
    if(s.score < 60) students.remove(s);
}

// 正确姿势 ✅
Iterator<Student> it = students.iterator();
while(it.hasNext()) {
    if(it.next().score < 60) it.remove();
}

3. 内存泄漏问题(C++选手注意!)

使用指针数组时要记得手动释放内存:

vector<Student*> students;
// ...添加元素
for(auto ptr : students) delete ptr; // 必须的!
students.clear();

五、性能优化黑科技

1. 批量添加的骚操作

一次性添加多个元素时,使用addAll()比循环add快10倍!

// 慢 ❌
for(String item : newItems) {
    list.add(item);
}

// 快 ✅
list.addAll(Arrays.asList(newItems));

2. 空间换时间的取舍

当需要频繁在头部插入时,可以考虑使用LinkedList。但根据实测,当数据量超过5000时,ArrayList的随机访问速度是LinkedList的100倍不止!

六、动态数组的"近亲们"

1. 环形缓冲区(处理高并发神器)

  • 固定大小的循环队列
  • 适合生产者-消费者模式
  • 无扩容开销,内存友好

2. 跳跃表(Redis的底层实现)

  • 通过多层索引加速查找
  • 插入/删除时间复杂度O(log n)
  • 比红黑树更好实现

七、常见面试题破解

Q:ArrayList和LinkedList的区别?

参考答案:

  1. 底层结构:数组 vs 双向链表
  2. 访问速度:O(1) vs O(n)
  3. 插入删除:尾部O(1),其他位置O(n) vs 任意位置O(1)
  4. 内存占用:连续内存 vs 每个元素多两个指针

Q:vector的capacity()和size()区别?

参考答案:

  • size():实际元素个数
  • capacity():当前分配的存储容量
  • 当size() == capacity()时会触发扩容

八、最后的小彩蛋 🎉

下次遇到女/男朋友问:“为什么游戏加载这么快?”
你可以回答:“因为用了对象池+动态数组预分配呀!”
(保证对方一脸崇拜 😎)

记住:动态数组虽好,但不要滥用哦!根据实际场景选择最合适的数据结构,才是真正的高端玩家~

从基本实现到高级优化:可伸缩数组的高效应用与实践 本文详细探讨了可伸缩数组的实现与性能优化,涵盖了从基础实现到高级优化策略的各个方面。我们首先介绍了可伸缩数组的基本概念和操作,包括其扩容机制的实现。随后,通过对扩容策略、内存管理、线程安全及缓存优化等方面的分析,我们探讨了如何在不同场景中提升可伸缩数组的性能。文章还通过实际应用案例,如动态列表、实时数据处理系统和文本编辑器的缓冲区管理,展示了可伸缩数组在不同应用中的广泛使用及其带来的性能提升。通过合理的实现和优化策略,可伸缩数组能够有效应对数据增长的挑战,保证系统的高效运行。 阅读详情

相关推荐

Docker部署FRP实现内网穿透

FRP是一款开源内网穿透工具,通过在公网服务器部署服务端(FRPS),内网设备运行客户端(FRPC)实现外部访问。支持TCP、UDP、HTTP等多种协议。部署时需配置服务端(如群晖NAS使用Docker)和客户端(如Windows下载可执行文件)。服务端需设置监听端口、控制面板及Token认证,客户端需指定服务器地址和相同Token。完成配置后可通过公网IP或域名访问内网资源,并在控制面板监控连接状态。

波哥技术栈 1599

C语言——伸缩型数组成员

       最近了解到TLV协议后,开始了对其的代码实现,并在期间发现了伸缩性数组这个眼熟却手生的东东,借此机会深挖了一下这个伸缩型数组成员(flexible array member)。 struct TLV_BODY // TLV报文 { short tag; // value类型 ...

Mastema 1548

LibTV保姆级教程:从提示词到AI视频成片全流程

AI视频生成技术正以前所未有的速度重塑内容创作行业,过去需要编剧、摄影、剪辑等多角色协作的复杂流程,如今借助AI绘画与图生视频等核心能力,一个人也能完成高质量短视频制作。理解提示词工程是掌控AI视频创作的关键,通过精准描述主体、环境、光线与运镜,可以显著提升生成画面的稳定性与专业度。而图生视频技术则让静态分镜自然流动,有效解决角色一致性与场景漂移等常见问题。这类工具已广泛应用于产品宣传、剧情短片、社交媒体内容生产等场景,大幅降低了视频创作门槛。本文以LibTV一站式AI视频创作平台为例,从核心概念到完整实操

weixin_29046035的博客 939

伸缩数组的错误用法,对于伸缩数组成员,一定要malloc内存。

##伸缩数组的错误性用法 之前学习和应用数组时,在声明数组变量时,长度都是固定的,无法动态的定义数组的长度。 如下: int max[]; //错误编译失败。 今天在阅读一份代码时,发现使用了伸缩数组,C99标准已经支持了变长数组。如下例子: struct ipmi_loop_req_info { uint8_t resv; /* always 0 */ ...

mikedadong的专栏 292

OnePlus救砖指南:线刷包与OTA全量包实战解析

本文详细解析了OnePlus手机救砖的两种核心方法:线刷包与OTA全量包。针对手机变砖的不同状况(如黑屏、能进Recovery等),文章提供了清晰的判断标准和对应的实战操作指南。重点阐述了线刷包作为终极救砖手段的底层原理与详细步骤,并对比了OTA全量包作为温和修复方案的使用场景与卡刷流程,旨在帮助用户安全、有效地恢复手机系统。

weixin_28312391的博客 1315

大华/华睿工业相机(摄像头)链接电脑,并用OpenCV打开

睿科是大华旗下机器视觉子公司,现在工业相机一般是华睿在产,要下载驱动程序,要到华睿官网哪里下载。由于我的电脑没有摄像头,所以摄像头序列化为0,电脑的第一个摄像头默认为0,序列号是0,1,2,3……,你是什么接口连接的就选择什么, 建议直接全选。我这里选择第二个,下载后点击安装,的你要点击识别右侧设置,设置。这个过程很简单,故不赘述。打开你的设备会在右边显示。

qq_48050838的博客 1万+

结构体的伸缩数组

*简介 伸缩数组(flexible array)这是C99对结构体功能的扩展.可伸缩性的体现在于,在结构体的原型声明时,可以声明一个没有指定数组长度的数组,在使用时通过malloc动态决定结构体变量的数组大小. *规则 ---伸缩数据必须是结构体的最后一个成员 编译报错:"error: flexible array member not at end of struct

king4ant的专栏 1678

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

m0_72224305的博客 4305

C语言中的动态数组实现:模拟Python列表的伸缩性

动态数组是一种非常灵活且强大的数据结构,通过手动管理内存,可以在C语言中实现类似Python列表的动态伸缩性。动态数组的扩展和收缩策略是实现高效内存管理的关键。在实际应用中,根据数据量的大小和变化频率选择合适的扩展和收缩策略。使用调试工具(如Valgrind)检测内存泄漏和越界访问。阅读和分析优秀的C语言代码,学习动态数组的高级用法。希望这篇博客能够帮助你深入理解C语言中的动态数组实现,提升编程能力。如果你有任何问题或建议,欢迎在评论区留言!

司徒鸿的博客 525

74、刀具磨损监测与寿命预测分析

本文综述了刀具磨损监测与寿命预测的研究现状,分析了力信号、功率信号、振动信号和声发射信号在刀具状态监测中的应用及其优缺点。介绍了当前常用的刀具寿命模型及故障诊断流程,并总结了基于不同信号的监测方法。文章指出,尽管已有多种方法在理论上取得进展,但在实际应用中仍面临挑战。未来研究方向包括采用更先进的神经网络、深入探索多信号融合技术以及有效利用工业大数据,以提升刀具状态识别的准确性与可靠性。

lstm7chronicler的博客 275

华为OD机试真题 新系统2026-04-01 C++ 实现【计算数列位置N的值】

如果其前面的M个元素中,存在值相同的元素,则该位置上的数值等于前面M个数中最大的数值与最小的数值之如果其前面的M个元素中,不存在值相同的元素,则该位置上的数值等于前面M个数中最大的数值与最小的数值之差;1、输入M、N两个数,则按照以下规则形成一个数列;两个整数,用逗号分割,分别表示M和N。一个整数,表示数列第N个位置上的数值。2、数列的前M个元素的值为1到M;请计算该数列第N个位置上的数值。N取值范围:1<= N<=50。M取值范围:3<=M<=10。

MISAYAONE的博客 1152

动态数组:程序员的伸缩自如神器(实战避坑指南)

比如Java的ArrayList默认扩容1.5倍,C++的vector是2倍,Python的list更狡猾——会预分配额外空间!这时候传统数组分分钟让你崩溃!上次我接手一个项目,用普通数组处理用户消息队列,结果上线当天就炸了——消息量突然暴增导致数组越界!下次面试官问你动态数组的实现原理,直接把这篇拍他脸上(开玩笑)!记住,工具没有好坏,只有合不合适。选择合适的数据结构,才能写出风骚的代码!咱们平时用的普通数组就像固定大小的收纳盒(重要!),装10个元素就只能是10个。动态数组的聪明之处在于它的。

cloudcruiser的博客 976

基于多模态融合的反无人机视觉跟踪算法研究

本研究提出了一种基于多模态融合的反无人机视觉跟踪算法,通过整合可见光、红外、深度等多种视觉信息源,提高了对无人机的跟踪精度和可靠性。设计并实现了多模态特征提取方法,针对不同模态图像的特点提取了有效的特征信息,为多模态融合提供了基础。研究了多种多模态融合策略,包括特征级融合、决策级融合和混合融合,并通过实验对比分析了它们的优缺点,确定了适合反无人机视觉跟踪的融合方法。选择并改进了跟踪算法,将多模态融合信息融入到跟踪过程中,提高了算法对复杂环境和无人机运动变化的适应性。

AI的内部世界的博客 1351

C语言中的伸缩型数组:看似简单,其实很巧妙

摘要:《CPrimerPlus》中介绍的C99新增特性——伸缩型数组成员,为数据包结构体定义提供了更优雅的解决方案。传统方法要么浪费空间,要么不够规范,而伸缩型数组成员(如uint8_t payload[])位于结构体末尾且不占空间,其实际长度由运行时决定。使用时需注意三点:必须是结构体最后一个成员、数组声明留空、需配合malloc动态分配空间。这一特性特别适合嵌入式通信协议解析等场景,能更灵活高效地处理变长数据包。

李述铜的笔记 854

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

伸缩型数组成员

在C primier plus中,第十四章的结构和其他数据形式,关于伸缩型数组成员。 程序清单有一个微小的瑕疵,现修改如下: 把原程序 pf1=malloc(sizeof(struct flex)+n*sizeof(double)); 改为: pf1=(struct flex *)malloc(sizeof(struct flex)+n*sizeof(double)); 因为mal...

LPJLBJ的博客 354

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C语言结构体-伸缩数组成员(c99)

1.伸缩型数组成员(c99) 伸缩型数组成员应当满足: 伸缩型数组成员必须是结构体最后一个成员; 结构中必须至少有一个成员; 声明类似于普通数组,但是它的方括号是空的。 struct inf{ float high; folat wei; char name[]; //伸缩型数组成员 }; 声明后,不能用name做任何事,因为还没有为其预留储存空间,因此需要用malloc()为其分配空间。 ...

Peterwatwec的博客 487

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

java数组伸缩_Java数据结构与算法--运用泛型编程实现自定义可动态伸缩的数组类...

使用java,运用泛型编程,实现一个自定义数组类,此类可以做到动态扩展数组长度和动态释放数组空间,同时可以支持各种数据类型(泛型)自定义类的一个好处是可以根据需求任意去扩充方法,这里开发了一些数组中常见的操作方法public class Array {private E[] data;private int size;/*** 构造函数,传入数组的容量capacity构造Array* @param...

weixin_29037455的博客 156

C/C++之变长数组(VLA)和可伸缩型数组成员

数组主要用来处理一系列同类型的数据集合,在C/C++中应用十分广泛。其中有两种特殊的数组,变长数组(VAL)和可伸缩型数组成员,应用得当的话,会非常方便。

飘零过客 5404

CH2 数组类4 - 动态数组(Array)

文章目录 前两篇本质上还是静态数组,静态数组容量是有限的。但有时我们无法预估将要使用的数组有多大,太大太小都不好。解决方案:数组容量是可伸缩的。本篇就是实现可伸缩的动态数组 ...

liu14116的博客 198

Java动态数组

1.Java动态数组的用法详解      Java动态数组是一种可以任意伸缩数组长度的对象,在Java中比较常用的是ArrayList,ArrayList是javaAPI中自带的java.util.ArrayList。下面介绍一下ArrayList作为Java动态数组的用法。 语法:add()是添加一个新的元素,remove()删除一个元素,size()获得ArrayList的长度。ArrayL...

Harrytsz的博客 2万+

C/C++中的柔性数组(可伸缩性数组)

在STL源码中的第2级空间配置器有一个联合定义如下: union obj { union obj* free_list_link;   char client_data[1];  }; 在侯大师的详细解释下,我总算对STL的空间配置器有一个总体印象。但对以上这个联合体的设计方式始终不得其所,client_data[1]这个数组,在空间分配中根本没有使用到嘛!它的设计初衷是什么呢?      

vgxpm的专栏 2603

伸缩型数组成员(C99)

C99具有一个称为伸缩型数组成员(flexible array member)的新特性。利用这一新特性可以声明最后一个成员是一个具有特殊属性的数组的结构。该数组成员的特殊属性之一是它不立即存在。第二个特殊属性是您可以编写适当的代码使用这个伸缩型数组成员,就像它确实存在并且拥有您需要的任何数目的元素一样。 声明一个伸缩型数组成员的规则: 伸缩型数组成员必须是最后一个数组成员。 结构中必须至...

weixin_30755393的博客 141

无锁队列之Mpmc动态可伸缩队列

(3)如果待消费索引队列中索引数目少于当前实际容量大小,说明索引被重新返还给了m_freeIndices队列,再次尝试从该队列取出索引坐冷板凳,该函数的实现参考。Mpmc索引队列管理底层数组容器的底层索引,可以在运行时将部分索引的使用权收回从而达到减小队列容量的目的,反之则可以增加队列容量。(2)如果(1)中decrease的数量不满足toDecrease的设定要求,继续从待消费索引多列中取出元素坐冷板凳。(2)如果(1)失败,则从待消费索引队列中尝试取出最旧的索引,弹出底层数组中该索引对应的数据。

weixin_40102543的博客 595
上一篇: 零基础也能懂的C语言入门指南(手把手版)
下一篇: 零基础玩转Mathematica:不用学语法也能搞定数学计算(超详细保姆教程)
普通网友
博客等级 码龄2年 117粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值