数据结构与算法学习笔记之 从0编号的数组

简介: 前言 数组看似简单,但掌握精髓的却没有多少;他既是编程语言中的数据类型,又是最基础的数据结构; 一个小问题:  为什么数据要从0开始编号,而不是 从1开始呢? 正文 带着问题进入学习 如何实现随机访问? 什么是数组? 数组(array)是一种线性表数据结构,它用一组连续的内存空间来储存一组具有相同类型的数据。

前言

数组看似简单,但掌握精髓的却没有多少;他既是编程语言中的数据类型,又是最基础的数据结构;

一个小问题:

 为什么数据要从0开始编号,而不是 从1开始呢?

正文

带着问题进入学习

如何实现随机访问?

什么是数组?

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

我们从定义来分析:

 

线性表:

是数据排成像一条线一样的结构。每个线性表上的数据最多有前后两个方向。诸如数组,链表,队列,栈等都是线性表结构。

 

连续的内存空间和相同类型的数据:

这个特性是数组“随机访问”速度飞快的缘由,这也导致了从数组中删除、插入数据,为了保证连续性,需要大量的工作量

 

计算机会给每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。

当计算机随机访问数组中的某个元素时,它会首先通过下面的寻址公式,计算出该元素的内存地址:

a[i]_address = base_address + i * data_type_size

data_type_siza表示数组中的每一个元素的大小。如果是int类型的数据,data_type_size为4个字节;

数组和链表的区别

链表适合插入、删除,时间复杂度为O(1),数组适合查找,但是这里要注意一下,时间复杂度并不是O(1),即便是排好序的数组,你用二分法查找,时间复杂度也是O(logn),

正确的描述为:数组支持随机访问,根据下标随机访问的时间复杂度为O(1)

 

低效的“插入”“删除”

插入操作

假设数组的长度为 n,现在,如果我们需要将一个数据插入到数组中的第 k 个位置,为了把第 k 个位置腾出来,给新来的数据,我们需要将第 k~n 这部分的元素都顺序地往后挪一位,下面我们分析一下时间复杂度

如果在数组的末尾插入元素,那就不需要移动数据了,这时的时间复杂度为 O(1),但如果在数组的开头插入元素,那所有的数据都需要依次往后移动一位,所以最坏时间复杂度是 O(n),因为我们在每个位置插入元素的概率是一样的,所以平均情况时间复杂度为 (1+2+…n)/n=O(n)

如果数组中的数据是有序的,我们在某个位置插入一个新的元素时,就必须按照刚才的方法搬移 k 之后的数据,如果数组中存储的数据并没有任何规律,数组只是被当作一个存储数据的集合。在这种情况下,如果要将某个数组插入到第 k 个位置

为了避免大规模的数据搬移,我们还有一个简单的办法就是

直接将第 k 位的数据搬移到数组元素的最后,把新的元素直接放入第 k 个位置。

 

删除操作

和插入类似,

如果删除数组末尾的数据,最好情况时间复杂度为 O(1);

如果删除开头的数据,则最坏情况时间复杂度为 O(n);

平均情况时间复杂度也为 O(n)

 

提高效率:

将多次删除操作中集中在一起执行,可以先记录已经删除的数据,但是不进行数据迁移,而仅仅是记录,当发现没有更多空间存储时,再执行真正的删除操作。这也是 JVM 标记清除垃圾回收算法的核心思想。

 

数组访问越界问题

C语言中的数据越界是一种未决行为,一般比较难发现的逻辑错误。相比之下,Java会有越界检查。

 

用数组还是容器?

数组先指定了空间大小,容器如ArrayList可以动态扩容。

1.希望存储基本类型数据,可以用数组

2.事先知道数据大小,并且操作简单,可以用数组
3.直观表示多维,可以用数组
4.业务开发,使用容器足够,开发框架,追求性能,首先数组。

 

为什么数组要从 0 开始编号?

由于数组是通过寻址公式,计算出该元素存储的内存地址:
a[i]_address = base_address + i * data_type_size
如果数组是从 1 开始计数,那么就会变成:
a[i]_address = base_address + (i-1)* data_type_size

 

以上内容为个人的学习笔记,仅作为学习交流之用。

 

作者:Dawnzhang 
出处:https://www.cnblogs.com/clwydjgs/p/9390488.html 
版权:本文版权归作者
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

小舟从此逝,江海寄余生。 --狐狸
目录
相关文章
|
2月前
|
算法 测试技术
【算法】二分算法——寻找旋转排序数组中的最小值
【算法】二分算法——寻找旋转排序数组中的最小值
|
2月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
8天前
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
9天前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
2月前
|
存储 算法 Java
深入算法基础二分查找数组
文章深入学习了二分查找算法的基础,通过实战例子详细解释了算法的逻辑流程,强调了确定合法搜索边界的重要性,并提供了Java语言的代码实现。
深入算法基础二分查找数组
|
2月前
|
算法
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()
|
3月前
|
存储
【数据结构OJ题】轮转数组
力扣题目——轮转数组
35 2
【数据结构OJ题】轮转数组
|
2月前
|
存储 Java 程序员
"揭秘HashMap底层实现:从数组到链表,再到红黑树,掌握高效数据结构的秘密武器!"
【8月更文挑战第21天】HashMap是Java中重要的数据结构,采用数组+链表/红黑树实现,确保高效查询与更新。构造方法初始化数组,默认容量16,负载因子0.75触发扩容。`put`操作通过计算`hashCode`定位元素,利用链表或红黑树处理冲突。`get`和`remove`操作类似地定位并返回或移除元素。JDK 1.8优化了链表转红黑树机制,提升性能。理解这些原理能帮助我们更高效地应用HashMap。
35 0
|
2月前
|
算法
【算法】模拟算法——外观数组(medium)
【算法】模拟算法——外观数组(medium)
|
2月前
|
算法
【算法】前缀和——除自身以外数组的乘积
【算法】前缀和——除自身以外数组的乘积
下一篇
无影云桌面