![eed8c364561847c72dd971f42601fe46.png](https://img-blog.csdnimg.cn/img_convert/eed8c364561847c72dd971f42601fe46.png)
1、Array概述
同数组不用,数组的大小在定义时已经确定,而在实际过程中数组需要根据数据量的大小自动更改数组大小。底层实现仍是数组,只是将数组进行封装,可以实现自适应的数组Array。
涉及的所有函数方法:
![61871e4b9b8eaeeff2334edca2baf146.png](https://img-blog.csdnimg.cn/img_convert/61871e4b9b8eaeeff2334edca2baf146.png)
2、Array数组实现思路
数组无非涉及增、查、改、删四种操作,查和改操作与平常数组操作相同。难点就在于增加元素和删除元素上。对于一般数组当索引index + 1 超过数组大小是就会报错。为了可以根据数据大小改变数组大小,引入capacity(容器)的概念。其中capacity >= size。如图
![11446aa38b080f4ff94f75bd16efdce5.png](https://img-blog.csdnimg.cn/img_convert/11446aa38b080f4ff94f75bd16efdce5.png)
注: 实际上capacity才是真正数组的大小,size只是capacity中存储数据的多少。 下面分别说一下增删改查的的实现思路
2.1、增加元素
如果增加后 size <= capacity 则直接将数据添加到数组中,如果增加后 size > capacity 则需要对数组进行扩容操作。扩容的方式也就是扩大为原来的2倍。
下面以在索引index=2,元素未5为例: 主要分为有无扩容的请况
1)增加元素-未扩容: 1. 复制元素向后移动 2. 插入元素到索引位置
![f85b9dd7e41052bef247625b8bb4fae4.png](https://img-blog.csdnimg.cn/img_convert/f85b9dd7e41052bef247625b8bb4fae4.png)
2)增加元素-扩容: 1. 扩容为原来的2倍,将原数据复制到新数组 2. 将索引之后的元素向后移一位 3. 插入元素
![807f3b53a7720755133ca63adb246959.png](https://img-blog.csdnimg.cn/img_convert/807f3b53a7720755133ca63adb246959.png)
扩容的方式就是开辟一块原capacity的大小2倍的空间,然后将原数组的数据拷贝到新开辟的数组当中。 在头部和尾部增加元素对应 index = 0 和 index = size - 1
程序实现:
public
2.2、删除元素
增加元素对应扩容,那么删除元素对应缩容,当删除元素后 size < capacity / 2的时候进行缩容。否则直接让对应位置等于 null 即可。 下面以删除索引为1的元素为例 : 主要分为有无缩容的请况 1)删除元素-未缩容的情况 : 1. 将要删除元素后面的数据向前移一位 2. 删除数据中最后一位的元素,索引为size(删除后size已经减 1)
![eec0770f8d78cdca79016735bc8e46e6.png](https://img-blog.csdnimg.cn/img_convert/eec0770f8d78cdca79016735bc8e46e6.png)
2)删除元素-缩容的情况 : 1. 将要删除元素后面的数据向前移一位 2. 删除数据中最后一位的元素,索引为size(删除后size已经减 1) 3. 进行缩容,将原数据复制到原数组大小一半的新数组中
![cdd2a55916b49b2012e5aef0b636d1af.png](https://img-blog.csdnimg.cn/img_convert/cdd2a55916b49b2012e5aef0b636d1af.png)
程序实现 :
public
2.3、改变元素
改变元素不涉及扩容或者缩容,没有特别的地方,直接修改即可。 下面以set(2, 5)为例 :
![5ca033a76a16081be0f12d0aa8bb6975.png](https://img-blog.csdnimg.cn/img_convert/5ca033a76a16081be0f12d0aa8bb6975.png)
代码实现:
void
2.4、查找元素
查找元素分为三种,查找是否有这个元素,查找这个元素所在位置,根据索引返回元素这三种。 查找是否有这个元素和查找这个元素所在位置代码实现相似,一个找到了返回 true,一个找到了返回 index。 1)查找是否有这个元素
public
2)查找这个元素所在位置
public
3、时间复杂度分析
1)增加元素的复杂度 最好的情况是向最后的位置添加元素复杂度为 O(1) ,最坏的情况是向头添加元素,因为需要数据整体向后移动,复杂度为 O(N) ,根据均摊复杂度得出复杂度为 O(N/2) = O(N),也就是说增加元素的复杂度为 O(N)。但是这仅仅是考虑没有扩容的情况产生。但是对于扩容的也是遍历一边数组进行复制的操作,所以复杂度也为 O(N)。 综上所述增加操作的时间复杂度为 O(N)
![c160bec062ad6b04fa108b2756d59010.png](https://img-blog.csdnimg.cn/img_convert/c160bec062ad6b04fa108b2756d59010.png)
2)删除元素的复杂度 删除元素的时间复杂度同增加元素完全相同。一个扩容一个缩容,实现机理相似。也就是说删除操作的时间复杂度也是 O(N) 级别。
![c7e675ef2cdf8c1df6fd79a7b086ecee.png](https://img-blog.csdnimg.cn/img_convert/c7e675ef2cdf8c1df6fd79a7b086ecee.png)
3)修改元素复杂度 修改操作利用了数组的优势,支持随机访问。也就是可以在 O(1)的复杂度的情况下完成操作。
![8ef7818e64615c5a2708970fab06f229.png](https://img-blog.csdnimg.cn/img_convert/8ef7818e64615c5a2708970fab06f229.png)
3)修改元素复杂度 修改操作对应三种情况,对于支持索引查找的get方法复杂为 O(1)。对于contain方法和find方法两者类似,需要遍历数组,最好的情况是在最开始就找到想要查找元素,最坏的情况是想要查找的元素在末尾,根据均摊复杂度,两者的复杂度为 O(N)。
![e51ded9b9a49b88bc28f04670e6393b4.png](https://img-blog.csdnimg.cn/img_convert/e51ded9b9a49b88bc28f04670e6393b4.png)
4、解决时间复杂度震荡的办法
对于时间复杂度的震荡发生在扩容和缩容的边界。addLast()导致扩容,removeLast()导致缩容,在边界反复添加和删除操作会导致时间复杂度震荡。导致时间复杂度一直维持在O(N)级别。
![b02658fee4ab3c189a172bbec19e1864.png](https://img-blog.csdnimg.cn/img_convert/b02658fee4ab3c189a172bbec19e1864.png)
产生的原因就是因为我们在 removeLst 的时候过于 Eager (激进),导致与 addLast() 的扩容操作相冲突,其实我们避开 / 2 和 * 2 就可以避免震荡问题,因此我在代码中将 removeLast 的 resize 触发改为 / 4.
public
5、Array具体实现函数
5.1、公有方法
getSize
5.2、私有方法
resize
6、最后
更多精彩内容欢迎大家关注我的微信公众号:TeaUrn <- ^ - ^
如果有问题或者疑问可以私信我或者微信上私信我。
也欢迎大家来我的主页:
首页 | 曲怪曲怪quguaiquguai.cn:8090![9d8b985c17756e31ae607512eff8f6f8.png](https://img-blog.csdnimg.cn/img_convert/9d8b985c17756e31ae607512eff8f6f8.png)
我在这里等你哦~~