数据结构之数组

在第一课的我们提到了数据结构,今天我来说说线性结构之数组

我们带着主要的问题去思考:
为什么说数组就查询快了,删除的效率跟删除的节点位置有关?

下面我拿java中的例子来说:

不知道各位小伙伴面试的时候是否经常会被问:
请你说说ArrayList与LinkedList的区别:
我相信大部分小伙伴都会说到ArrayList查询快,LinkedList适用于需要频繁的插入与删除操作的场景
还有重要的就是数据结构不同啊,比如ArrayList是数组,动态数组,而LinkedList是链表(主要是说数据结构就不多讨论这个面试题了)
….
image.png
回到主题数组

数组

讲到他为什么会查询高效的问题,就由下面这个例子来说明一下:

上学的时候是否有升旗的时候需要排队呢?比如教导说你们班升旗的时候就在占这块地方了,其他的班也依次有地方站好如图:
未命名文件.jpg

001-005就代表这每一个班级,我们从图中可以看到他们是有序的就跟你从初一升到初二,然后会来新的初一学生,然后他们的班级名称就是006了
但是又会发现这块场地只能容下5个班级啊,但是你升班,也会有新的班级毕业,所以学校招生也只能招离开了多少个班级,然后开多少个班级了,

什么是数组:

存储有限数据类型的集合,在班级的例子中,我们知道每个班级都有名字,而在数组也会为每一空间取一个称呼叫下标

  1. ![未命名文件 (8).png](https://cdn.nlark.com/yuque/0/2021/png/611698/1619835309016-ec19113b-d905-4135-ba0a-ac37401ffd0a.png#align=left&display=inline&height=342&margin=%5Bobject%20Object%5D&name=%E6%9C%AA%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6%20%288%29.png&originHeight=342&originWidth=540&size=8168&status=done&style=none&width=540)

如图:上面的班级对应下标,班级是学校里面的,而数组中的每个数据被称为元素,

怎么找到指定的元素呢?为什么数组查找就快呢?

在学校里面我们可以通过指定的班级去找到指定人,而在数组中我们就是通过下标去获取元素,如在数组中我要获取001的值怎么获取呢,通过数组名[下标获取]

String[] arr = new String[]{"001","002","003","004","005"}
//就获取到下标为0的元素值=001
String  classOne= arr[0]

那为什么说数组查询就快呢?

这就涉及了内存结构,数组在内存中他是顺序存储的,

                                                            ![未命名文件 (9).png](https://cdn.nlark.com/yuque/0/2021/png/611698/1619858298690-9bdd39da-cbd9-4940-886b-e18863eb9b40.png#align=left&display=inline&height=261&margin=%5Bobject%20Object%5D&name=%E6%9C%AA%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6%20%289%29.png&originHeight=261&originWidth=550&size=5911&status=done&style=none&width=550)

上图就如在内存中开辟一块空间,然后数组的元素他是顺序排例的,而他的特性是可以根据下标快速找到指定元素,像他的内存地址一般也是连续的

扩展说明: 为什么要这样画图呢? 因为我们new一个数组都是去堆里面申请一块内存空间,然后存储的元素就在申请的这块内存空间中,可能我画多了,因为我们这次数组只有5个元素,不是画5个就好了? 我这是想让小伙伴知道这样的规则

总结下:
这里主要是讲出数组的一个特点,顺序存储,然后他要是在内存开辟一块空间他里面的元素内存地址是连续的
因为他是顺序存储,所以在数组中查找元素通过下标就可以找到了,所以他的时间复杂度就是O(1)
也基于他是可以通过下标访问的所以在修改的层面是他也是O(1)

String[] arr = new String[]{"001","002","003","004","005"}
//把下标为0的值改成006
arr[0] = "006"

那删除操作的时间复杂度多少呢?
看过ArrayList集合的删除应该了解过一个方法 System.arraycopy,这个方法就是把数组的元素从一个下标复制到另一个数组中[可以是相同的数组],所以这个方法的实现就是,删除下标为2的值我们就需要把后面的元素都往前移动一个位置,所以数组的删除跟删除的位置有关,所以他的时间复杂度就是O(n)
image.png
插入呢?[这里说的是动态数组]
插入元素就稍微复杂点因为他会涉及扩容
image.png

还是这5个元素,我们现在要从头部插入,没有位置怎么办呢?他就会重新去申请一块内存空间,如ArrayList集合申请的内存空间就是原空间的1.5倍,然后把插入的元素放到新申请的数组中【这里画的是俩倍大小】,怎么操作的呢,申请一块新内存把旧数值的复制到新数组中,在插入需要插入的值,而时间复制度也跟插入的位置有关
image.png

是否注意到,如果我不需要扩容的时候,我是从尾部插入的时间复杂度是否也是O(1)呢,
中间插入也是需要移动元素的数量,O(n)的复杂度,

总结下数组的特性:

数组查询效率高,根据下标就可以查询到值了,但是他删除,插入根据位置有关,效率稍微低点,所以我们在使用数组这个数据结构的时候在推荐在读多写少的环境中