数据结构基础之动态数组
动态数组
数组的局限性
目前为止所实现的数组类,有一个非常严重的局限性,就是这个数组实际使用的还是一个静态数组,内部容量有限。在实际使用的时候,我们往往无法预估要在这个数组中存入多少个元素。
解决方案
在这种情况下,如果容量首次开太大,可能会浪费很多空间,但容量太小,又有可能不够用。这时候,需要有一种解决方案使得这个数组的容量是可伸缩的,也就是所谓的动态数组。
思路
- 首先,原数组data,容量capacity为4,数组中元素size为4
- 然后新开一个数组new data(原数组data),开的空间要比原来大一些(从4–>8)
- 遍历原数组data,赋值到new data中。此时容量capacity为8,数组中的元素size为4
- 本身data指向4个空间的数组,现在指向8个空间的数组(new data也指向它)
图解操作:
- 总结
整个过程封装在一个函数内,对于new data这个变量在函数执行完便失效了,而data由于是类的成员变量,与整个类的生存周期一致(只要类还在使用,data就是有效的) - 细节
对于原来4个空间的数组,由于没有对象指向它,所以利用java的垃圾回收机制将其回收
具体代码实现
|
动态数组的优势
使用上述方法,让我们这个数组类拥有容量的动态伸缩的能力,所以在用这个数组类的时候,使用者不必关心数组容量是否够用的问题
简单的时间复杂度分析
前提
到目前为止,都主要以编程的思想来实现我们代码的逻辑,而对于这段代码的性能方面,我们一无所知。因此才需要使用复杂度分析的方式,来解析我们的代码
定义
- 通常我们用O(1),O(n),O(logn),O(n^2)来描述一个算法的时间复杂度
- O描述的是算法的运行时间和输入数据之间的关系
以代码做演示:
注:实际上,我们忽略了很多常数。比如for循环里,从nums数组中取数,还有sum相加的过程等等,所花的时间都是常量。
- 实际时间T=c1*n+c2,c1表示n次操作每次所耗费的时间常数,c2表示完成算法内其他操作所耗费时间
- 为什么用大O,叫O(n)? ,因为忽略常数,实际时间T=c1*n+c2
- 举例:
- T = 2*n + 2 O(n)
- T = 2000*n + 10000 O(n)
- T =1*n*n + 0 O(n^2) 渐进时间复杂度,描述n趋近无穷的情况
- T =2*n*n + 300n + 10 O(n^2)
分析动态数组的时间复杂度
添加操作
- addLast(e) 向数组末尾添加一个元素,O(1)意味着,消耗时间跟数据的规模大小无关,无论数组中有多少个元素,都能在常数时间里完成
- addFirst(e)** O(n)
- add(index, e) 取决于index的位置,考虑极端情况则是演变成addLast(e)的O(1)操作,亦或者是退变成addFirst(e)的O(n)的操作,平均操作O(n/2)=O(n)
- 在算法时间复杂度分析上,通常我们关注的是最坏,最糟糕的情况。
综上所述,对于我们的动态数组来说,添加操作时间复杂度是O(n)级别的。
删除操作
- removeLast(e) 在末尾删除一个元素,O(1)意味着,消耗时间跟数据的规模大小无关,无论数组中有多少个元素,都能在常数时间里完成
- removeFirst(e)** O(n)
- remove(index, e) 取决于index的位置,考虑极端情况则是演变成removeLast(e)的O(1)操作,亦或者是退变成removeFirst(e)的O(n)的操作,平均操作O(n/2)=O(n)
- 在算法时间复杂度分析上,通常我们关注的是最坏,最糟糕的情况。
综上所述,对于我们的动态数组来说,删除操作时间复杂度是O(n)级别的。
修改操作
- set(index, e) 是O(1)
- 修改操作在动态数组中非常简单,只需要知道要修改的元素所对应的索引,直接利用set(index, e)。这个时间复杂度是O(1)级别的,这是数组最大的优势,专业术语是,支持随机访问。只要知道索引是谁,便可以一下子访问到它
查询操作(根据索引和元素进行查找)
- get(index) :O(1)
- contains(e) : O(n)
- find(e) : O(n)
总结:增: O(n); 删: O(n); 当只对最后一个元素操作依然是O(n),因为存在resize()
改:已知索引O(1),未知索引O(n); 查 : 已知索引O(1),未知索引O(n)
我们可以轻松的使用索引,去检索数组中的元素,那么在性能上便有非常强的优势。
resize()复杂度分析
防止复杂度震荡
复杂度震荡
- 假设现在我们有一个数组,容量是n,并且装满了元素。
- 这时候,我想添加一个元素,显然是需要进行扩容,容量变为2n,耗时O(n)的时间。
- 但是此时,我又删除了一个元素触发了缩容操作,耗时O(n)的时间。
- 当我们每次触发缩容或扩容操作,都会耗费O(n)额复杂度,那么这便是复杂度的震荡
分析
在特殊情况下,我们频繁的添加和删减操作,导致过于着急的去扩容或缩容
图解:
解决方案
可以采用一种相对懒惰的策略。
- 比如说,一个满的数组,容量n,添加元素需要进行扩容,容量变为2n
- 但在这时,在进行删除元素后,不立即进行缩容操作,而是再等等
- 如果后面一直有删除操作的话,删除到整个数组容积的1/4,再触发缩容操作。缩容数组的1/2,而不是直接缩容到1/4
- 此时,数组中存在1/4的元素,还预留了1/4的空间
通过这样的策略,防止了复杂度的震荡,从而有效的提升整体的性能
具体代码实现
|
- 本文链接:https://loubobooo.com/2018/07/29/初学数据结构-动态数组/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!
数据结构基础之动态数组相关推荐
- 2021-9-下旬 数据结构-线性表-动态数组-java代码实现
信管的数据结构讲的太水了,遂重学(看的网课:恋上数据结构与算法,讲的very good),为算法学习打基础(都大三了还在打基础),顺便在leetcode上跟进一些相关的题,记录在这里,这里最方便复习 ...
- golang数据结构初探之动态数组slice
动态数组slice slice 又称动态数组,依托于数组实现,可以方便的进行扩容和传递,实际使用时比数组更灵活.但正是因为灵活,实际使用时更容易出错,避免出错的最好方法便是了解其实现原理. 特性速览 ...
- 算法与数据结构基础四----数据结构基础之动态数据结构基础:链表上
接着上一次https://www.cnblogs.com/webor2006/p/15195969.html的数据结构继续往下学习,这次会进入一个非常重要的数据结构的学习----链表,这个是未来学习复 ...
- java动态数组的实现的_Java实现数据结构之【动态数组】
数组是学习编程语言时较先接触到的一种数据结构,本章基于Java的静态数组实现动态数组,并进行简单的复杂度分析 数组相信各位都知道,那什么是动态数组呢?我们定义一个数组后,一般长度会直接定义好,如果数组 ...
- 【数据结构基础】之数组介绍,生动形象,通俗易懂,算法入门必看
前言 本文为数据结构基础数组相关知识,下边将对数组的定义.性质及结构,数组的各种玩法如循环遍历数组.查找数组最大值.数组元素的位移等,二维数组的定义及用法等进行详尽介绍~ Java全栈学习路线可参考: ...
- 数据结构基础之动态顺序表详解
文章目录 前言 一.动态顺序表的概念 二.顺序表的结构体 三.基本接口 1.SeqListInit(初始化数组) 2.SeqListDestory(销毁数组) 3. SeqListCheckCapac ...
- 基于java的数据结构学习——泛型动态数组的封装
public class Array<E> {private E[] data;private int size;// 构造函数public Array(int Capacity){dat ...
- 数据结构与算法 —— 动态数组
一.基础与细节 1. 扩容策略 无论是 C++ STL 中的向量 vector 还是 Java Collections 中的 ArrayList,采用的扩容策略是_capacity <<= ...
- 基础数据结构【二】————动态数组,单向链表及链表的反转
DEMO1: 动态分配变量(链表,而静态数组是线性表,意味着动态数组访问和遍历复杂度为O(n),而插入和删除复杂度为O(1),而静态数组线性表则完全相反) int* intptr = new ...
最新文章
- 谷歌Waymo自建车厂,L4级无人车量产指日可待
- CSS之window的视图属性
- MITRE 发布防御知识库 Shield
- 中文短文本的实体识别实体链接,第一名解决方案
- fasta文件中序列的排序
- 小程序中上传图片并进行压缩(二)
- 可以下载MapInfo地图吗?
- 【考研】2021年哈尔滨工业大学计算机考研「复试」经验贴
- 怎么在html中加水印,如何在h5网页添加水印
- SNMP原理和MIB库
- Android App应用市场功能的框架图
- 用文氏图表示映射满射单射及函数的关系
- php网页显示中文乱码的解决办法!
- 响度与响度处理经验谈(上)响度测量
- 为什么成年人都不学习了
- mac上Latex的安装及使用教程
- Zephyr参考文档
- 20051111: 最近玩WOW好像太多了
- 成都中科院计算机研究所招聘,2017年中科院成都计算机应用研究所考研复试分数线以及复试通知...
- 买网站服务器需要什么软件有哪些东西,建网站的软件有哪些,哪些常用?
热门文章
- sugarcrm_通过SugarCRM休息
- 做人要大方包容、善解人意,凡事包容,凡事相信,凡事盼望,凡事忍耐
- 一、pycharm的使用技巧和好用插件
- 内存溢出的几种原因和解决办法是什么?
- AI智能检测识别平台EasyCVR出现卡顿及反应慢的原因分析以及解决方法
- python安装pyparsing后提示No module named ‘pyparsing‘
- linux下搭建HTTP代理服务器
- 使用Docker加速器
- TYVJ 2054 [Nescafé29]四叶草魔杖 最小生成树 状态压缩/背包DP
- [CSS] CSS实现鼠标移入图片放大效果