数组:为什么很多编程语言中数组都从0开始编号

数组:为什么很多编程语言中数组都从0开始编号

如何实现随机访问

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

①线性表:数据排成像一条线一样的结果,每个线性表上的数据只有前或后两个方向。数组、链表、队列、栈也是线性表结构

非线性表有二叉树、堆、图等,数据之间并不是简单的前后关系

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

可以进行随机访问,但为了保证连续性,需要做大量的数据搬移工作

数组实现下标随机访问数组元素:长度为10的int类型的数组int[] a = new int[10]举例,给a[10]分配了一块连续内存空间1000~1039,计算机会给每个内存单元分配一个地址,可以通过地址来访问内存中的数据,当计算机需要随机访问数组中的某个元素时,首先通过寻址公式a[i]_address = base_address + i * dat,计算出该元素存储的内存地址.

数组和链表的不同:

数组是适合查找操作,但是查找的时间复杂度并不为O(1),即便是排好序的数组,用二分查找时间复杂度也是O(logn),正确的表述是:数组支持随机访问,根据下标随机访问的时间复杂度为O(1),链表适合插入、删除,时间复杂度为O(1)

低效的插入和删除

插入操作:如果是在数组的末尾插入元素,就不需要移动数据,时间复杂度为O(1),但如果在开头插入元素,需要所有的数据都往后移动一位,所以最坏复杂度为O(n),平均情况复杂度为O(n).

假设数组a[10]中存储了如下5个元素:a,b,c,d,e,我们需要将元素x插入到第3个位置,我们只需要将c放入到a[5],将a[2]赋值为x即可,这样时间复杂度就会降为O(1)

删除操作:要删除第k个位置的数据,可以将多次删除操作集中在一起执行

数组a[10]存储了8个元素,a,b,c,d,e,f,g,h,要依次删除a,b,c三个元素,为了避免d,e,f,g,h几个数据被搬移3次,先记录下已经删除了的数据,每次删除操作并不是真正的搬移数据,只是记录数据已经被删除,当数组没有更多空间存储数据时,再触发执行删除操作导致的数据搬移

这就是JVM标记清楚垃圾回收算法的核心思想

数组的访问越界问题

int main(int argc,char * argv[]{
   int i = 0 ;
   int arr[3] = {0};
   for(;i <= 3 ;i++){
     arr[i] = 0;
     printf("hello world\n");
   }
   return 0 ;
   })

这段代码会打印无限行"hello wolrd",因为数组大小为3,a[0],a[1],a[2],所以当i = 3的时候,数组a[3]访问越界

在c语言中,只要不是访问受限的内存,所有内存空间都是可以自由访问的,a[3]会被定位到某块不属于数组的内存地址上,而这个地址正好是存储变量I 的内存地址,那么a[3] = 0 ,相当于 i = 0 ,会导致代码无限循环

数组越界在C语言是一种未决行为,并没有规定数组访问越界时编译器应该如何处理,因为访问数组的本质就是访问一段连续内存,只要数组通过偏移计算得到的内存地址是可用的,程序就不会报错

函数体内的局部变量存在栈上,且连续压栈,在linux进程的内存布局中,栈区在高地址空间,从高到低增长,i占4字节,接着arr占12字节,内存从高到低:地址依次是:i,a[2],a[1],a[0],a[3]通过寻址公式,计算得到的正好是i 的存储地址,所以a[3]=0,相当于i = 0 .变量i和arr在相邻地址,且i比arr的地址大,所以arr越界正好访问到i

c语言关于数组的内存分配说明?????????

容器能否完全替代数组

针对数组类型,很多语言都提供了容器

什么时候用数组更合适点:

①Java ArrayList无法存储基本类型,比如Int、long,需要封装为Integer、Long类,如果特别关注性能,或希望使用基本类型,可以选用数组

②若数据大小事先知道,并且对数据的操作非常简单,直接使用数组

对于业务开发,直接使用容器足够,如果做非常底层的开发,性能的优化需要做到极致,使用数组

为什么大多数编程语言,数组从0开始编号,而不是从1开始?

从数组存储的内存模型上看,下标最确切的定义应该是偏移offset,用a来表示数组的首地址,a[0]是偏移为0的位置,就是首地址,a[k]表示偏移k个type_size的位置,所以计算a[k]的内存地址需要a[k]_address = base_address + k * type_size,但是如果从1开始计数,计算数组元素a[k]的内存地址为:a[k]_address = base_address + (k-1)*type_size,从1开始编号,每次随机访问数组元素都多一次减法运算,对于cpu来说,多一个减法指令,所以为了效率 的优化,减少一次减法操作,数组选择从0开始编号

二维数组的内存寻址公式是?

对于m*n的数组,a[i] [j](i < m,j < n)的地址为address = base_address + (i * n + j) * type_size

按行连续存放,行序有限的存储 float a[3] [5]

a_00 a_01 a_02 a_03 a_04

a_10 a_11 a_12 a_13 a_14

a_20 a_21 a_22 a_23 a_24

a[i] [j]的首地址= p + (i * col +j)* 4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值