数组的理解和使用

2020-09-10  本文已影响0人  文景大大

前言

本篇文章需要解决如下的问题:

  1. 数组有哪些特点?
  2. 数组的插入、查找、删除元素时间复杂度如何分析?
  3. 数组在使用过程中需要注意什么?
  4. 数组和容器类ArrayList的区别是什么?它们各自的优缺点是什么?
  5. 数组下标为什么是从0开始的?

一、数组的定义

数组是一种线性表数据结构,它用一组连续的内存空间来存储一组具有相同类型的数据。

在这里,线性表的意思是,数据像一条线一样组织起来的,每个线性表上的数据只有向前和向后两个方向,比如数组、链表、队列、栈等;而非线性表就比如树、堆、图之类的。

二、 数组的特点

三、 数组的插入和删除

3.1 插入操作

3.2 删除操作

删除操作在最好和最坏情况下的时间复杂度为O(1)和O(n),平均时间复杂度也是O(n),那有什么办法可以优化删除操作,减少搬运数据的过程,提高效率呢?

我们完全可以将多次删除操作集中在一起进行。当一开始删除时,我们可以将待删除的元素标记为已删除,等到数组已分配空间不够用的时候,触发一次清除操作和搬运数据操作。

四、 数组的越界

在C语言中,数组越界会使得程序陷入无限死循环;

在高级语言中,比如Java,会抛出运行时异常ArrayIndexOutOfBoundsException;

建议在程序中,使用数组中元素时,都需要做越界检查,或者捕获该异常进行处理。

五、 数组和容器

ArrayList和数组有什么区别,它们各自的优缺点是什么,以及在什么场景下使用哪个比较合适?

首先,ArrayList的底层实现就是基于数组的,但是它封装了很多数组的实现,比如插入元素和删除元素,我们直接调用add和remove即可,不用关心数据的搬移和优化等操作。

其次,ArrayList是可以自动扩容的,每次扩容都是原来的1.5倍,而数组一旦初始化好空间了,就不能更改大小,除非自己申请一块更大的连续内存空间,再手动搬运数据。ArrayList把扩容和搬运数据的操作都封装起来了,使用起来更加便捷。然而,每次扩容都涉及申请空间和搬运数据,所以,如果一开始能确定数据大小的话,就尽量就指定大小。

List<String> sl = new ArrayList<String>(100); 

然后,ArrayList的泛型只支持封装类,不支持基本数据类型,比如Integer、Long,对于如下的操作都会有自动装箱和拆箱操作,会损耗一定的性能。

List<String> sl = new ArrayList<String>(100); 
sl.add(15);
int num = sl.get(1);

还有,如果你能提前确定好数组的大小,并且代码逻辑很简单,用不着ArrayList的方法,那么就可以直接使用数组,而不是容器。如果你想要用到二维数组,也推荐使用数组,而不是容器,因为int[][]明显比ArrayList<ArrayList<>>更加的直观。

最后,对于平常的业务逻辑开发,建议使用容器类,比较简单省心,一点点的性能损耗对于整个应用来说算不得什么;但是如果你是用来写一些公共的底层方法,需要考虑很高的性能,那么就推荐使用数组。

六、数组下标为什么从0开始

上一篇 下一篇

猜你喜欢

热点阅读