手撕数据结构与算法-数组

简介: 数组是数据结构中最简单、最常用的数据结构,是一种线性表数据结构,在内存中是一块连续的存储空间,是有限个相同类型变量所组成的有序集合。数组中的每一个变量叫做元素。

前言

开篇一张图,知识全靠吹!

开篇点个赞,博主能上天!

本系列文章已收录到github:

1. 什么是数组?

数组是数据结构中最简单最常用的数据结构,是一种线性表数据结构,在内存中是一块连续的存储空间,是有限个相同类型变量所组成的有序集合。数组中的每一个变量叫做元素

线性表:线性表从字面意义上来理解是数据的排列像一条线的结构,只有前后两个方向。线性表中的元素都是一对一的关系,除了首尾元素外,其他元素都是首尾相连的。除了数组,链表、队列、栈也是线性表结构的。

以整型数组为例,我们new一个整型数组int[] array = new int[]{1,2,3,4};,数组内的元素存储的元素是1、2、3、4。那么数组的存储形势就如下图:

数组图解.png数组图解.png

在上图中粉色的格子代表已经被占用了的存储单元,绿色的格子代表数组的存储位置,白色的格子代表空闲的存储单元。数组的下标是从0开始的。所以元素和下标的对应关系是:

2. 数组的优缺点

谈起数组的优点,我相信大部分的人都会说随机访问这个堪称杀手锏的特性,那么它为什么能够做到随机访问呢?

我认为主要有两点:

  • 连续的存储空间
  • 线性表结构

正因为它是在内存中是一块连续的存储空间,并且是线性表结构,前后元素都是一一对应的,所以才能够让他拥有随机访问的特性。在上一篇文章数据结构与算法-开篇当中我们介绍了时间复杂度和空间复杂度,这里就不对说了,比如我们要查找上边的数组中的第三个元素,那么打印出array[2]就能够获取到第三个元素值,这里输出的是3,因为数组支持随机访问,所以根据下标随机访问的时间复杂度为O(1),因为它的查找操作只执行了一次。

这样的结构使它的查询操作非常的方便,有利也有弊,它的插入、删除操作就会变得低效,因为要保证数据的连续性,所以执行插入、删除操作就需要做大量的数据搬移工作。如果这个时候一个数组的随机访问正好访问到没有值得下标上就会获取不到值。如果不搬移数据将中间的空洞补充上,那么内存就不连续了。我们在数组的操作中在详细介绍。

3. 数组的基本操作

3.1 添加元素

  • 中间插入

    中间插入稍微复杂一些,每个元素都有自己的下标,如果一个元素想要插入到数组的中的除首尾的位置,那么插入的该位置上的元素都要向后移动,给新的位置腾出空间,保证连续性。

  • 尾部插入

    尾部插入这种情况比较简单,直接把元素放到数组尾部的空闲位置即可,等同于更新元素的操作。

    QZJyrj.pngQZJyrj.png

3.2 删除元素

删除操作和插入操作的过程正好相反,如果删除的元素在数组的中间,那么其后的元素都要向前移动。

QZNRII.pngQZNRII.png
QZNqds.pngQZNqds.png

3.3 更新元素

carbon (1).pngcarbon (1).png

这里更新元素的时间复杂度为O(1)

3.4 读取元素

carbon.pngcarbon.png

这里读元素的时间复杂度为O(1)

4. 容器能够代替数组吗?

针对数组类型,很多语言都提供了容器类,例如Java的List,如果你是一个Java程序员,那么你应该清楚ArrayList,对它应该非常的熟悉,和数组对比它有哪些优势呢?为什么开发的过程中经常使用它,最大的优势就是封装了对数组的操作,例如前面说的插入和删除,如果使用ArrayList还有一个优势是它支持动态扩容,当容器不够大的时候会自动扩容1.5倍,我们完全不需要关心底层的实现逻辑。那么什么时候使用数组更合适呢?有一下几点:

  • ArrayList无法存储基本数据类型,例如int、long需要封装为Integer、Long。这里的装箱、拆箱操作有一定的性能损耗,如果特别关注性能,希望使用基本类型,那么就可以选择数组。
  • 对数据只是简单的存储操作,那么选择数组效率更好些。
  • 当做一些底层开发的时候数组可能用的比较多,比如一些框架。都是比较要求性能的。

5. 参考

《漫画算法》

《数据结构与算法之美》

6.结尾求关注环节

在我看来后端程序员应该学的有三大基础知识"数据结构与算法""计算机系统""操作系统Linux"。在这个互联网寒冬时代,是不是我们的衣服穿得不够多?彻夜难眠的我(纯属扯淡,哈哈)决定带领大家一起学习三大基础知识,本次开篇系列是《手撕数据结构与算法》,每一个系列更完就会开启下一个系列,大家不要着急。可以关注我的公众号,持续追更、持续学习。

注意、注意 前方高能======>

如果你对我的这个系列感兴趣可以关注我的公众号,带你走上”超神之路、拿高薪offer、当上技术专家、出任个大厂、迎娶白富美、走上人生巅峰,想想还有点小激动。” (哈哈,请允许我吹个🐂)

来了 来了 他来了 他带着二维码来了!!!

欢迎扫码关注哦!!!欢迎扫码关注哦!!!
目录
相关文章
|
1月前
|
存储 Java 程序员
数据结构之 - 深入了解数组数据结构
数据结构之 - 深入了解数组数据结构
38 6
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
1月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
99 64
|
3月前
|
算法 测试技术
【算法】二分算法——寻找旋转排序数组中的最小值
【算法】二分算法——寻找旋转排序数组中的最小值
|
3月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
1月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
30 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
1月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
21 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
2月前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
3月前
|
存储 算法 Java
深入算法基础二分查找数组
文章深入学习了二分查找算法的基础,通过实战例子详细解释了算法的逻辑流程,强调了确定合法搜索边界的重要性,并提供了Java语言的代码实现。
深入算法基础二分查找数组
|
3月前
|
算法
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()