L04_什么是数组

数组作为基础数据结构,从0开始编号源于寻址公式简化和历史沿袭。这种设计允许直接计算内存地址,减少CPU指令。文中探讨了数组的随机访问、插入、删除操作的时间复杂度,并指出在特定场景下,数组比容器更具性能优势。同时,文章提到了Java中的ArrayList在动态扩容时的内存消耗,并建议业务开发使用容器,底层开发则可选用数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导读

在大部分编程语言中,数组都是从 0 开始编号的,但你是否下意识地想过,为什么数组要从 0 开始编号,而不是从 1 开始呢? 从 1 开始不是更符合人类的思维习惯吗?

在这里插入图片描述

1、什么是数组

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

2、数组的操作实现

2.1、随机访问

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

2.2、插入

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

2.3、删除

如果我们要删除第 k 个位置的数据,为了内存的连续性,也需要搬移数据,不然中间就会出现空洞,内存就不连续了。

和插入类似,如果删除数组末尾的数据,则最好情况时间复杂度为 O(1);如果删除开头的数据,则最坏情况时间复杂度为 O(n);平均情况时间复杂度也为 O(n)。

2.4、数组越界

Java 本身就会做越界检查,比如下面这几行 Java 代码,就会抛出 java.lang.ArrayIndexOutOfBoundsException。

int[] a = new int[3];
a[3] = 10;

3、容器能否代替数组

相比于数字,java中的ArrayList封装了数组的很多操作,并支持动态扩容。一旦超过存储容量,扩容时比较耗内存,因为涉及到内存申请和数据搬移。

4、数组适合的场景

  • Java ArrayList 的使用涉及装箱拆箱,有一定的性能损耗,如果特别关注性能,可以考虑数组。
  • 若数据大小事先已知,并且涉及的数据操作非常简单,可以使用数组。
  • 表示多维数组时,数组往往更加直观。
  • 业务开发建议使用容器,如果是底层开发,如网络框架,性能优化,那么选择数组。

5、数组为什么从0开始编号

5.1、寻址公式

由于数组是通过寻址公式,计算出该元素存储的内存地址:

a[i]_address = base_address + i * data_type_size

如果数组是从 1 开始计数,那么就会变成:

a[i]_address = base_address + (i-1)* data_type_size

对于CPU来说,多了一次减法的指令。

5.2、历史原因

C 语言设计者用 0 开始计数数组下标,之后的 Java、JavaScript 等高级语言都效仿了 C 语言,或者说,为了在一定程度上减少 C 语言程序员学习 Java 的学习成本,因此继续沿用了从 0 开始计数的习惯。实际上,很多语言中数组也并不是从 0 开始计数的,比如 Matlab。甚至还有一些语言支持负数下标,比如 Python。

``` #define Drv89x_OCP_STAT_1_ADDR 0x01u #define Drv89x_OCP_STAT_2_ADDR 0x02u #define Drv89x_OCP_STAT_3_ADDR 0x03u #define Drv89x_OLD_STAT_1_ADDR 0x04u #define Drv89x_OLD_STAT_2_ADDR 0x05u #define Drv89x_OLD_STAT_3_ADDR 0x06u uint8 VaDrv89x_u_RxBuffOCP11[2]; static void Drv89x_Read_DiagRegister(void) { static l_read_chip_id = Drv89x_CHIP1; switch(l_read_chip_id) { case Drv89x_CHIP1: if(VeDrv89x_u_GLOABL_FAULT[l_read_chip_id].Drv89xFault_Global_OLD != DRV8912_DIAG_NOERROR) { VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OLD_STAT_1_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOLD11,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OLD_STAT_2_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOLD12,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OLD_STAT_3_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOLD13,l_read_chip_id); } if(VeDrv89x_u_GLOABL_FAULT[l_read_chip_id].Drv89xFault_Global_OCP != DRV8912_DIAG_NOERROR) { VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OCP_STAT_1_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOCP11,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OCP_STAT_2_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOCP12,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OCP_STAT_3_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOCP13,l_read_chip_id); } break; case Drv89x_CHIP2: if(VeDrv89x_u_GLOABL_FAULT[l_read_chip_id].Drv89xFault_Global_OLD != DRV8912_DIAG_NOERROR) { VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OLD_STAT_1_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOLD21,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OLD_STAT_2_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOLD22,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OLD_STAT_3_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOLD23,l_read_chip_id); } if(VeDrv89x_u_GLOABL_FAULT[l_read_chip_id].Drv89xFault_Global_OCP != DRV8912_DIAG_NOERROR) { VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OCP_STAT_1_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOCP21,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OCP_STAT_2_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOCP22,l_read_chip_id); VaDrv89x_u_TxBuff[0] = REG_READ_Drv89x|Drv89x_OCP_STAT_3_ADDR; VaDrv89x_u_TxBuff[1] = 0u; Drv89x_SpiTransmit(VaDrv89x_u_TxBuff,VaDrv89x_u_RxBuffOCP23,l_read_chip_id); } break; default: break; } }```该函数的功能是分两个周期去读取两个芯片的各6个寄存器,VaDrv89x_u_RxBuffOCP11这种缓冲区都是uint8的含有两个元素的数组,请问能怎么优化该函数?
03-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值