数据结构与算法之美笔记——数组

2024-06-09 09:48

本文主要是介绍数据结构与算法之美笔记——数组,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘要:

数组」是最简单基本的数据结构,属于一种「线性表数据结构」,它有着可以快速随机访问元素的优势,但也有低效的删除和插入操作,容器对数组的封装会简化对数组的操作,也会对带来一些劣势。

特性原理

数组是其实是一组连续的内存空间,用来存储一组相同类型的数据,它是一种线性表数据结构。那什么是线性表,线性表就是数据排成一条线一样的结构,每个数据最多只有前后两个方向,像链表、栈、队列等都是线性表数据结构。

数组的另一个特点就是连续内存空间存储,并且都是存储的同类型数据。因为这个特点,数组中每个元素的地址都可以使用基础地址与下标通过寻址公式快速计算出来。

a[i]_address=base_address + i * data_type_size

base_address 就是这块连续内存的首地址
data_type_size 就是元素的大小,例如元素是 int 类型时,data_type_size 大小就为 4

所以数组的随机访问只需通过一个公式就可以完成,时间复杂度也就是 O ( 1 ) O(1) O(1)

插入与删除操作

因为数组需要满足连续内存空间存储要求,导致删除或者插入操作会变得低效。如果插入元素到数组末尾时,直接插入就可以,但当插入元素是在数组头时需要将元素搬移,再将数据插入数组首位,所以数组的插入操作最好时间复杂度和最坏时间复杂度分别是 O ( 1 ) O(1) O(1) O ( n ) O(n) O(n)

将元素插入已经连续存储 n 个数据的数组时,插入元素的位置有 n 种可能,每种可能下数组元素需要进行搬移操作的次数分别为 n , n − 1 , n − 2 , . . . , 3 , 2 , 1 n,n-1,n-2,...,3,2,1 n,n1,n2,...,3,2,1 次,平均时间复杂度为

1 n + 2 n + 3 n + . . . + n n = n × ( n + 1 ) 2 n = n + 1 2 = O ( n ) \frac{1}{n} + \frac{2}{n} + \frac{3}{n} + ... + \frac{n}{n}=\frac{\frac{n\times{(n+1)}}{2}}{n}=\frac{n+1}{2}=O(n) n1+n2+n3+...+nn=n2n×(n+1)=2n+1=O(n)

但是插入操作在特定情况下时间复杂度降为 O ( 1 ) O(1) O(1)。当数组不要求元素有序时,插入操作就可以将要插入位置的元素搬移到数组元素的最后,再把元素插入相应位置,时间复杂度就为 O ( 1 ) O(1) O(1)

删除操作与插入操作相似,最好时间复杂度为 O ( 1 ) O(1) O(1),最坏时间复杂度为 O ( n ) O(n) O(n),平均时间复杂度为 O ( n ) O(n) O(n)。但删除操作在某些场景下,不是非要追求数组中元素连续性时,可以先把数据标记为删除,当数组没有存储空间时再统一删除被标记的数据,这样可以把多次数据搬移操作整合为一次。

对比容器类

容器类是对数组的封装,用 Java 中的 ArrayList 举例,它将数组的插入、删除操作细节封装了起来,并且支持动态扩容,数组存储空间不够时需要创建一个更大空间的数组,再将旧数组中的元素搬移到新数组中。虽然容器支持动态扩容,但扩容操作比较消耗资源,使用容器类时如果能够估算大概的数据容量在初始化容器类时可以初始化空间的大小,避免在扩容过程中进行的资源消耗。

虽然 ArrayList 有简化数组操作和动态扩容储多优势,但 ArrayList 不能存储基本类型,需要使用包装类型,在使用时就会增加自动装箱和自动拆箱操作,肯定会增加一些性能消耗,同时对多维数组的表示不是很直观,ArrayList 表示二维数组 Object[][] array 需要写为 ArrayList<ArrayList> array

虽然很多语言对数组提供了容器类,但数组也有自己的适用场景,比较关注性能时,表示多维数组时都可以考虑直接使用数组。

课后题目

分析一下二维数组的寻址公式。

假设大小为 m * n 大小的二维数组 a[i][j], i &lt; n , j &lt; m i\lt{n},j\lt{m} i<nj<m,寻址公式为

a[i][j]_address = base_address + (i * n + j) * data_type_size


文章中如有问题欢迎留言指正
数据结构与算法之美笔记系列将会做为我对王争老师此专栏的学习笔记,如想了解更多王争老师专栏的详情请到极客时间自行搜索。

这篇关于数据结构与算法之美笔记——数组的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1044833

相关文章

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

AssetBundle学习笔记

AssetBundle是unity自定义的资源格式,通过调用引擎的资源打包接口对资源进行打包成.assetbundle格式的资源包。本文介绍了AssetBundle的生成,使用,加载,卸载以及Unity资源更新的一个基本步骤。 目录 1.定义: 2.AssetBundle的生成: 1)设置AssetBundle包的属性——通过编辑器界面 补充:分组策略 2)调用引擎接口API

《offer来了》第二章学习笔记

1.集合 Java四种集合:List、Queue、Set和Map 1.1.List:可重复 有序的Collection ArrayList: 基于数组实现,增删慢,查询快,线程不安全 Vector: 基于数组实现,增删慢,查询快,线程安全 LinkedList: 基于双向链实现,增删快,查询慢,线程不安全 1.2.Queue:队列 ArrayBlockingQueue:

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

操作系统实训复习笔记(1)

目录 Linux vi/vim编辑器(简单) (1)vi/vim基本用法。 (2)vi/vim基础操作。 进程基础操作(简单) (1)fork()函数。 写文件系统函数(中等) ​编辑 (1)C语言读取文件。 (2)C语言写入文件。 1、write()函数。  读文件系统函数(简单) (1)read()函数。 作者本人的操作系统实训复习笔记 Linux

【数据结构】线性表:顺序表

文章目录 1. 线性表2. 顺序表2.1 概念及结构2.2 接口实现2.3 顺序表的问题及思考 1. 线性表 线性表是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式

LVGL快速入门笔记

目录 一、基础知识 1. 基础对象(lv_obj) 2. 基础对象的大小(size) 3. 基础对象的位置(position) 3.1 直接设置方式 3.2 参照父对象对齐 3.3 获取位置 4. 基础对象的盒子模型(border-box) 5. 基础对象的样式(styles) 5.1 样式的状态和部分 5.1.1 对象可以处于以下状态States的组合: 5.1.2 对象

DDS信号的发生器(验证篇)——FPGA学习笔记8

前言:第一部分详细讲解DDS核心框图,还请读者深入阅读第一部分,以便理解DDS核心思想 三刷小梅哥视频总结! 小梅哥https://www.corecourse.com/lander 一、DDS简介         DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有低成本、低功耗、高分辨率、频率转换时间短、相位连续性好等优点,对数字信

数据结构9——排序

一、冒泡排序 冒泡排序(Bubble Sort),顾名思义,就是指越小的元素会经由交换慢慢“浮”到数列的顶端。 算法原理 从左到右,依次比较相邻的元素大小,更大的元素交换到右边;从第一组相邻元素比较到最后一组相邻元素,这一步结束最后一个元素必然是参与比较的元素中最大的元素;按照大的居右原则,重新从左到后比较,前一轮中得到的最后一个元素不参4与比较,得出新一轮的最大元素;按照上述规则,每一轮结