hualinux java 1.11:你用对数组了吗?

目录

一、java中的数组 

二、通过操作分析数组的优缺点

2.1 读取

2.2 查找

2.3 插入

2.4 删除

三、总结


数组对于初学者来说使用波频率也挻高的,所以有必须简单说一下。

数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。

一、java中的数组 

java中的数组是默认是无序的,所谓的无序是说其值保存是没有规律性,无序的

数组(Array)用一组连续的内存空间来存储一组具有相同类型的数据。

比如下图的一组数组

 

二、通过操作分析数组的优缺点

比如我们下载建立一个数组,是关于菜类的

String[] arr= {"生菜","油麦菜","大白菜","小白菜","芹菜"};

它们的内存分配如下图所示:因为String是对象放在堆中,栈只保存首地址

为了方便理解我就把图简单弄成下面这样的:后来都是用这个简图来表示

 

我们对以下4种操作进行分析

读取:查看数据结构中某一位置上的数据。对于数组来说,这意味着查看某个索引所指的数据值。例如,查看索引2上有什么菜,就是一种读取。

查找:从数据结构中找出某个数据值的所在。对于数组来说,这意味着检查其是否包含某个值,如果包含,那么还得给出其索引。例如,检查" 小白菜"是否存在于菜清单之中,给出其对应的索引,就是-一种查找。

插入:给数据结构增加一个数据值。对于数组来说,这意味着多加一个格子并填入一个值。例如,往购物清单中多加一项"菠菜", 就是一种插入。

删除:从数据结构中移走-一个数据值。对于数组来说,这意味着把数组中的某个数据项移走。例如,把购物清单中的"大白菜"移走,就是一种删除。

本章我们]将会研究这些操作在数组上的运行速度。同时,我们也将学到第一个重要理论:

操作的速度,并不按时间计算,而是按步数计算。

为什么呢?

因为,你不可能很绝对地说,某项操作要花5秒。它在某台机器上要跑5秒,但换到一台旧一点的机器,可能就要多于5秒,而换到一台未来的超级计算机,运行时间又将显著缩短。所以,受硬件影响的计时方法,非常不可靠。

然而,若按步数来算,则确切得多。如果A操作要5步,B操作要500步,那么我们可以很肯定地说,无论是在什么样的硬件上对比,A都快过B。因此,衡量步数是分析速度的关键。

此外,操作的速度,也常被称为时间复杂度。在算法中我们提到速度、时间复杂度、效率、性能,但它们其实指的都是步数。

事不宜迟,我们现在就来探索上述4种操作方式在数组上要花多少步。
 

2.1 读取

读取是按下标读的,一步就够了,知道索引号,就可以基于开始地址进行计算,只计算一次就够了。

例如:菜清单数组的索引和内存地址,如下图所示。

如果我们要找“小白菜”,知道它的索引号为3,直接到arr[3]的值就是内存首地址,再通过内存首地址读String对象的值就行了

 

2.2 查找

还是找“小白菜”,如果按查找的方式,那就得从索引0开始逐个读取值并进行判断是否是“小白菜”

索引0的值不是想要的,下一个索引1上

索引1的值也不是想要的,下一个索引2上

索引2的值也不是想要的,下一个索引3上 

.

索引3 找到了,是想要的,计算机不用再往后跳了,因为结果已经得到。

在这个例子中,因为我们检查了4 个格子才找到想要的值,所以这次操作总计是4 步。

这种逐个格子去检查的做法,就是最基本的查找方法——线性查找

但在那之前,我们再思考一下,在数组上进行线性查找最多要多少步呢?

如果我们要找的值刚好在数组的最后一个格子里(如本例的“芹菜”),那么计算机从头到尾检查每个格子,会在最后才找到。同样,如果我们要找的值并不存在于数组中,那么计算机也还是得查遍每个格子,才能确定这个值不在数组中。

于是,一个5 格的数组,其线性查找的步数最大值是5,而对于一个500 格的数组,则是500。

以此类推,一个N 格的数组,其线性查找的最多步数是N(N 可以是任何自然数)

可见,无论是多长的数组,查找都比读取要慢,因为读取永远都只需要一步,而查找却可能需要多步。

 

2.3 插入

往数组里插入一个新元素的速度,取决于你想把它插入到哪个位置上。

假设我们想要在购物清单的末尾插入"包菜"。那么只需一步。因为之前说过了,计算机知道数组开头的内存地址,也知道数组包含多少个元素,所以可以算出要插入的内存地址,然后一步跳到那里插入就行了。图示如下。

但在数组开头或中间插入,就另当别论了。这种情况下,我们需要移动其他元素以腾出空间,于是得花费额外的步数,如果字符数组不够的话,还得重新写一个数组,也可以使用动态数据List,list对象会重新申请一块大小是原来容量的两倍的内存空间,然后将当前所有元素以及待添加元素复制到新的内存空间中。

如上所示,整个过程有4 步,开始3 步都是在移动数据,剩下1 步才是真正的插入数据。

最低效(花费最多步数)的插入是插入在数组开头。因为这时候需要把数组所有的元素都往右移。

于是,一个含有N 个元素的数组,其插入数据的最坏情况会花费N + 1 步。即插入在数组开头,导致N 次移动,加上一次插入

 

2.4 删除

最后要说的“删除”,则相当于插入的反向操作。

数组的删除就是消掉其某个索引上的数据。

我们找回最开始的那个数组,删除索引2 上的值,即"大白菜"。

结果,整个删除操作花了3 步。其中第1 步是真正的删除,剩下的2 步是移数据去填空格。

所以,删除本身只需要1 步,但接下来需要额外的步骤将数据左移以填补删除所带来的空隙。

跟插入一样,删除的最坏情况就是删掉数组的第一个元素。因为数组不允许空元素,当索引0 空出,那么剩下的所有元素都要往左移去填空。

对于含有5 个元素的数组,删除第一个元素需要1 步,左移剩余的元素需要4 步。而对于500个元素的数组,删除第一个元素需要1 步,左移剩余的元素需要499 步。可以推出,对于含有N个元素的数组,删除操作最多需要N 步。

 

三、总结

数组在以下标随机读取的速度是很快的,但是查找、删除、插入相对是很慢的,数组越长越慢!

所以数组适合放数据以下标方式读取,不适合做查找、删除、插入操作。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值