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

本文深入探讨Java中数组的特性,包括读取、查找、插入和删除等操作的时间复杂度,揭示了数组作为基本数据结构在不同场景下的优势与局限。

目录

一、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 步。

 

三、总结

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

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值