数据结构之数组

本篇是数据结构与算法之美学习笔记

每一种编程语言中基本都有数组。

数组的定义:

数组(array)是一种线性表数据结构,它用一组连续的内存空间来存储一组具有相同类型的数据。
从上面的定义中有几个关键词

首先它是一个线性表

线性表
线性表就是数据排列成一条先一样的结构,每个线性表上的数据最多只有前和后两个方向。除了数组,链表,队列,栈等也是线性表结构
非线性表
二叉树,堆,图等。之所以是非线性,是因为数据之间并不是简单的前后关系。

然后它是连续的内存空间和相同的数据类型

有了这两个限制,才能让数组可以随机访问。当然有利就有弊,这两个限制也让数组的很多操作变得低效,比如删除和插入操作,为了保证连续性需要做大量的数据搬移工作。

数组是如何根据下标实现随机访问的?

比如一个长度为10的int类型的数组int[] a = new int[10],
在这里插入图片描述
从图中可以看到,计算机给数组a分配了一块连续的内存1000-1039.其中内存块的首地址为base_address=1000。

我们知道计算机会给每一个内存单元分配一个地址,计算机通过地址来访问内存中的数据。当计算机要访问数组中的某个元素的时候就会通过下面公式寻找地址

a[i]_address = base_address + i*data_type_size

这里的data_type_size表示数组中每个元素的大小,因为例子中是int所以大小为4

为什么数组的插入和删除是低效的?

插入操作:

假如数组的长度为n,如果我们需要将一个数据插入到数组中的第k个位置,为了把第k个位置腾出来,需要把第k~n这部分的元素都顺序的往后挪一位,操作复杂。

如果在数组的末尾插入元素,那就不需要移动数据了,插入比较简单,单是如果在数组的头部插入元素就复杂了,需要把所有的数据都往后移动一位。

如果一个数组中的数据是有序的,那我们在某一个位置插入一个新的元素的时候就必须得按照上面的方法移动k之后的数据,但是数组中存储的数据如果没有任何规律,这时候,如果想要把某个元素插入到k位置,为了避免大规模的数据搬移,有个简单的办法就是:直接把k位置的数据搬到数组的最后面,把新元素放到第k个位置。

删除操作:

跟插入数据类似,如果我们要删除第k个位置的数据,为了内存的连续性,也需要搬移数据,不然中间就会出现空洞。

在某些情况下,如果我们不要求数据必须是连续的,那么删除的时候可以不真删除,只是把这个元素标记为已删除,当组空间不够用的时候,在触发一次真正的删除,这样就大大减少了删除操作导致的搬移操作。

其实JVM的核心垃圾算法就是这个思想

ArrayList

java中的ArrayList相当与一个动态数组,支持扩容。它可以把很多数组操作的细节封装起来,比如数组的插入和删除。

数组在定义的时候,因为需要给它分配连续的内存空间,需要预先指定其大小,当存放的数据大于其大小的时候,我们需要从新分配一块更大的空间,把原来的复制过去在插入新的元素。

ArrayList中,当空间不够用的时候,它会自动扩容为原来的1.5倍的大小。

因为扩容设计到内存的申请和数据的搬移,这是比较耗时的,所以,如果事先能确定数据的大小,做好在创建ArrayList的时候指定其大小

虽然ArrayList比数组好用,不过有些时候使用数组会更好一些。

1)因为ArrayList无法存储基本类型,int long等需要封装成Integer,Long类,而自动装箱和拆箱的操作也会有一定的性能消耗,所以如果关注性能或者想用基本类型就选用数组

2)如果数据的大小已经知道,并且对数据的操作简单,可以直接使用数组

3)当使用多为数组的时候,用数组表示起来更加直观比如int[][]arr;而用容器的话则需要这样定义ArrayList arr。

在开发中,一般情况下直接使用ArrayList就可以,如果是偏底层的开发比如网络框架开发等需要更高的性能,使用数组更合适。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值