精华内容
下载资源
问答
  • 为什么数组从0开始

    千次阅读 2014-06-07 21:56:20
    为什么C语言的数组从开始呢?

    为什么C语言的数组从零开始呢?我觉得要理解这个问题,首先要有两个概念——地址偏移


    注意下面两个语句:

    array[10]

    *(array+10)

    这两条语句都是指向同一个元素。这两条语句是等价的。


    即是说,array[0]就是*(array+0)


    数组的下标就是对array这个数组进行偏移。这是硬件特性决定的。

    因为数据都是存放在内存地址里的,而数据的获取方式,是先得到一个数据的地址,然后对其进行偏移。


    如果数组从1开始计算,那么获取数组的第一个元素表达方式就是array[1]

    但是数组的第一个元素的地址就是array,CPU每次获取元素需要减去1。

    即必须这样做:*(array + 1 - 1)

    其中+1操作是数组的下标,-1操作是为了获得正确的元素地址。

    如果数组从1开始,会多了减1这个操作,增加了CPU的运算,浪费CPU资源。


    为了提高CPU的效率,只需要简单把数组从1开始修改为从0开始就可以了。



    如果还不是很明白,可以看一下等差公式

    an=a1+(n-1)d

    其中n是第n个,d是两个数之间相差的数,这里设为1。


    于是CPU为了获取数组的第n个元素,首先获得a1的地址,然后再从该地址出发,加上n-1,此时的地址就是所需的元素地址。但是每次都要进行-1操作,-1操作也是要消耗时间的,这样很浪费CPU资源。于是语言设计者决定数组从0开始,这样这公式就可以化为

    an=a0+n

    少了-1这一步骤,提高了CPU的效率。

    展开全文
  • 在大部分编程语言中,数组都是0开始编号的,但你是否下意识想过,为什么数组0开始编号,而不是1开始呢? 从1开始不是更符合人类的思维习惯吗?下面以这个问题来学习数组。 如何实现随机访问? 什么是数组?...

    1. 数组:为什么很多编程语言中数组都是从0开始?

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

    数组的基本概念与特性

    什么是数组?

    什么是数组?估计你心中已经有了答案。不过,这里还是总结一下。数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据
    这里定义里有几个关键词,理解了这几个关键词,就能彻底掌握数组的概念了。

    线性表(Linear List)。顾名思义,线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。除了数组,链表、队列、栈等也是线性表结构。

    而与它相对立的概念是非线性表,比如二叉树、堆、图等。之所以叫非线性,是因为在非线性表中,数据之间并不是简单的前后关系。

    总结下数组的特性

    • 第一是线性表(Linear List)。
    • 第二是连续的内存空间和相同类型的数据。

    正是因为这两个限制,它才有一个堪称“杀手锏”的特性 “随机访问” 。但有利就有弊,这两个限制也让数组的很多操作变得非常低效,比如要想在数组中删除、插入一条数据,为来保证连续性,就需要左大量的数据搬移工作。

    如何实现随机访问?

    数组到底是如何实现根据下标随机访问数组元素的?
    例如:长度为 10 的 int 类型的数组 int[] a = new int[10]

    1. 计算机给数组 a[10] ,分配了一块连续内存空间 1000 ~ 1039 ;
    2. 内存块的首地址为 base_address = 1000 ;
    3. 计算机会给每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。

    当计算机需要随机访问数组中的某个元素时,它会通过下面的寻址公式,计算出该元素存储的内存地址:
    a[i]_address = base_address + i * data_type_size

    arr[i] 首地址 = 数组内存块首地址 + 数据类型大小 * i,其中 i 为偏移量,其中 data_type_size 表示数组中每个元素的大小。

    上面这个例子里面:
    base_address :内存块的首地址。
    data_type_size : 表示数组中每个元素的大小,比如目前数组中存储的是 int 类型数据,所以 data_type_size 就为 4 个字节。

    数组时间复杂度

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

    1. 数组是一种线性表;
    2. 连续的内存空间和相同类型的数据。
      由于第二个性质,数组支持 “随机访问”,根据下标随机访问时间复杂度为 O(1),但是在数组中删除、插入数据时需要做数据搬移工作。

    低效的“插入”和“删除”操作

    1. 插入操作

    假如数组的长度为 n,我们需要将一个数据插入到数据的第 k 个位置,则需要将 [k , n] 位元素都顺序地往后挪动一位。

    • 最好的情况:时间复杂度为O(1),此时在数组末尾插入元素。
    • 最坏的情况:时间复杂度为O(n),此时在数组开头插入元素。
    • 平均的情况:时间复杂度为O(n),因为在每个位置插入元素的概率相同,故(1+2+3+......+n)/ n = O(n)

    2. 删除操作

    和插入操作一样,为了保证内存的连续性,删除操作也需要搬移数据。

    • 最好的情况:时间复杂度为O(1),此时删除数组末尾的元素。
    • 最坏的情况:时间复杂度为O(n),此时删除数组开头的元素。
    • 平均的情况:时间复杂度为O(n),因为删除每个位置的元素的概率相同,故(1+2+3+…+n)/ n = O(n)。

    更高级用法

    在某些特殊场景下,在不追求数组中数组的连续时,我们将多次删除操作集中在一起执行,会提高删除的效率?
    例如:假设有一个数组 a , 长度为 10,存储了 8 个元素,分别为 a,b,c,d,e,f,g,h 。现在我们依次删除 a,b,c 三个元素:

    a = [a,b,c,d,e,f,g,h];
    

    为了避免 d,e,f,g,h 这个几个数据会被搬移 3 次,我们先记录已经删除的数据(每次删除操作并不是真正的搬移数据,只是记录数据已经被删除)。当 a 数组没有空间存储数据时,这才触发依次真正的删除操作,这样就减少了删除操作导致的数据搬移。

    上述这个操作其实就是 JVM标记清除垃圾回收算法 的核心思想。

    3. 警惕数组访问越界

    在 C 语言中,只要不是访问受限的内存,所有的内存空间都是可以自由访问的。如果疏忽会造成严重的后果。当然,Java语言会自动检测。

    4. 总结
    **
    数组是最基础、最简单的数据结构。数组用一块连续的内存空间,来存储相同类型的一组数据,最大特点就是随机访问元素,并且时间复杂度为 O(1)。但是插入、删除操作也因此比较低效,时间复杂度为O(n)。

    数组和链表的区别

    • 数组支持随机访问,根据下标随机访问的时间复杂度为O(1),注意数组查找,即便是排好序的数组,使用二分查找时间复杂度为O(logn)。
    • 链表适合插入、删除、时间复杂度为O(1)

    最后总结一下:为什么大多数编程语言中,数组要从 0 开始编号,而不是从 1 开始呢?

    • 第一:历史原因, c 语言设计者用 0 开始计数数组下标,之后 Java、JavaScript等高级语言都效仿 C 语言,因此继续沿用从 0 开始计数的习惯。部分语言数组不是从 0 开始计数的,比如 Matlab,还有部分语言支持负数下标,如 Python。

    • 第二:从数组存储的内存模型上来看,“下标”最确切的定义应该是 “偏移(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 开始编号,而不是 1 开始。

    以上谢谢大家,求赞求赞求赞!

    💗 大佬们随手关注下我的wx公众号【一角钱小助手】和 掘金专栏【一角钱】 更多题解干货等你来~~

    展开全文
  • 数组的下标为什么0开始而不是从1开始

    万次阅读 多人点赞 2020-02-25 18:45:56
    如果从1开始,则a[i]的地址= 首地址 + (i-1)*每个数据所占的长度。 是不是前一种更好计算呢。 再举个例子: 1、数组在内存中申请是,所申请的内存是一段连续的内存地址; 2、例:int[] a=new int[3];申请一段:int ...

    数组是一段连续的空间,要求a[i]就是求它的地址,然后找到它。
    在这里插入图片描述

    如果从0开始,则a[i]的地址= 首地址 + i*每个数据所占的长度;
    如果从1开始,则a[i]的地址= 首地址 + (i-1)*每个数据所占的长度。
    是不是前一种更好计算呢。

    再举个例子:
    1、数组在内存中申请是,所申请的内存是一段连续的内存地址;
    2、例:int[] a=new int[3];申请一段:int 数据类型的数组,a 为变量,数组长度为:[3];
    3、这个数组所申请的内存地址是连续的
    (假设所申请的:第一个内存地址为:1008,第二个为:1009,第三个为:1010);
    但我们只知道:一、变量:a,它只拿到第一个内存地址1008;二、它的数组空间为3个;
    4、a[0]——把a拿到的内存地址:1008 + 0 = 1008 (指向第一个内存地址);
    a[1]——把a拿到的内存地址:1008 + 1 = 1009 (指向第二个内存地址);
    a[2]——把a拿到的内存地址:1008 + 2 = 1010 (指向第三个内存地址);
    所以:数据下标从 [0] 开始的意义也在于此!(当然,这是理解版的)。
    (备注):如果你写a[3],它就报错了,越界错误,因为你只申请了3个内存空间。

    展开全文
  • 对于学习过编程语言的人来说,相信绝大多数人都会有这样的疑问:我们平时计数,通常是开始计数的,为什么在编程语言中,数组的下标是0开始计算的呢?  这是因为,C语言中,下标的含意是:当前元素到第一个...

      对于学习过编程语言的人来说,相信绝大多数人都会有这样的疑问:我们平时计数,通常是从一开始计数的,为什么在编程语言中,数组的下标是从0开始计算的呢?
      这是因为,C语言中,下标的含意是:当前元素到第一个元素的偏移量。第一个元素的下标自然就是0,第二个元素的下标为1,第n个元素的下标为n-1。
      这样处理能带来什么好处呢?
      我们知道,C语言的数组是存储在一片连续的内存空间中的。C编译器就可以直接通过第一个元素的地址,即数组地址,和相应元素的下标[即距首元素的偏移量]来得到它的地址。如:

    char arr[] = "hello world!";

      假设arr[0]的地址为10000,编译器可以通过10000 + 2来获取a[2]的地址。从编译器的角度来讲,数组下标[索引]从0开始更为高效。


    展开全文
  • C语言数组元素下标为何0开始

    万次阅读 多人点赞 2016-05-06 11:24:51
    很多同学可能在学习数组时会有这个疑问,下标为什么不从1开始呢?从1开始不是更符合大家的日常习惯吗?生活中我们通常说第1个,而不是第0个。的确,有些计算机语言如早期的Pascal语言,数组元素的下标是从1开始的。...
  • 把python 数组,量化为从1开始数组

    千次阅读 2014-09-09 15:11:35
    问题描述: 比方我有一个数组:[10,12,3,4,9]
  • 程序风格---数组下标全部从1开始

    千次阅读 2010-06-10 09:53:00
       实际使用中数组下标从1开始,即0下标空着不用即可!    实际上数组dData有14个元素,即dData[0]到dData[13]  但实际使用中dData[0]不用,使用dData[1]到dData[13]  
  • 数组

    千次阅读 2020-10-23 09:27:15
    在本章中,我们将看看另一种数据结构叫做数组数组能存放多个值。数组几乎是所有编程语言的一个特性。 shell 也支持它们,尽管以一个相当有限的形式。即便如此,为解决编程问题,它们是非常有用的。 什么是数组? ...
  • lua中的数组下表默认而且推荐从1开始 如果真的想要数组下标 0 开始:  days = {[0]="Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} 注意:...
  • 数组特性 数组的一大特性:随机访问,这个在实际开发中大家也经常使用到。 数组地址 如何理解随机访问?假设有个数组int a[10],它的起始地址值为0x1000(address),那么当你访问第n个数据时(即a[n]),实际上是...
  • 数组下标为什么0开始:a.初步理解:b.加深理解: 1.数组的由来: // 变量声明 int a = 1; int b = 2; int c = 3; int d = 4; ... int n = 20; // 一个int类型4个字节,一个字节占8位 a.字面引申: ...
  • 数组——数组中存放1-10个整数

    千次阅读 2019-09-05 11:49:37
    新建一个数组,里面存放...4. 由于数组索引是0开始,所以 计数器 i 适合 0 开始,但是0开始,最后空数组里存的是0-9的数字,但是题目是1-10整数,所以需要加 1 5. 代码实现如下: var arr = []; for (var ...
  • 数组的下标,为什么0开始

    万次阅读 2018-10-18 09:13:52
    为什么数组的下标是0开始,而不是从1开始呢?从1开始不是更符合人们的习惯么。 这个问题,稍后回答,先聊聊数组的基本特性。 数组(Array)一种线性表数据结构,用一组连续的内存空间,存储一组相同类型的数据 ...
  • 先说说为什么C语言的数组0开始:众所周知,C语言的数组是直接操作内存,那我们肯定得内存的寻址开始说起,以“以行为主序”的分配为例:设数组的基址为LOC(a c1 c2),每个数组元素占据l 个地址单元,那么...
  • 特殊矩阵的压缩存储(数组下标0开始存储)

    千次阅读 多人点赞 2019-01-05 15:15:51
    用一维数组压缩存储 对称矩阵 对称矩阵的特点: a[i][j] = a[j][i] ...a[0][0] 开始,把每行元素都依次存储进一维数组 存储时:a[i][j] 在一维数组 A[ ]中的下标就是该元素前面元素的个数:k= i×(...
  • 数组下标为什么是0开始

    千次阅读 2017-08-30 10:49:08
    大家是否会觉得数组下标0开始很烦,下标0开始就代表第一个,下标1就是第二个,是不是觉得特别别扭?那为什么会0开始计呢? int[] a=new int[]{1,2,3,4,5};   这里有5个值,首先我们假设数组在内存中开辟的5...
  • 也不是所有的高级程序语言都是如此,比如Python数组下标就支持负数。
  • PHP 多维数组将下标0开始

    千次阅读 2018-03-16 17:13:12
    点击链接加入群【php/web 学习课堂】:https://jq.qq.com/?_wv=1027&k=5645xiw 欢迎大家加入,一起讨论学习 ... //自定义一个数组,模拟成在数据库里提取出来的 $array = [ '2018-3-2'=>
  • 下标0开始2.数组如何初始化?A: int a[10]={ } //大括号里不写值初始化值为0;不写,初始化为随机数Int b[] = {1,2,3,4,5,6,7,}编译,链接,执行(编译时得到数组大小)X = sizeof(b) :结果:28数组空间大小的算法...
  • 新手小白学JAVA 数组 数组工具类 二维数组

    万次阅读 多人点赞 2021-04-02 08:28:55
    数组下标是0开始的,下标的最大值是数组的长度减1 1.2 创建数组 数组的创建方式一般分为动态初始化和静态初始化 动态初始化 int[] a = new int[5]; 静态初始化 int[] b = new int[]{1,2,3,4,5}; int[] c = {1,2,3...
  • 1 为什么很多编程语言中数组都是 0 开始编号 1.1 效率原因 1.2 历史原因 2 数组的特点 2.1 随机访问 2.2 低效的“插入”和“删除” 2.2.1 低效原因 2.2.2 改进方法 3 数组越界问题 4 容器和数组用哪个更好 ...
  • 今天开始好好学数据结构01】数组

    千次阅读 多人点赞 2019-08-23 11:52:13
    面试的时候,常常会问数组和链表的区别,很多人都回答说,“链表适合插入、删除,时间复杂度O(1);数组适合查找,查找时间复杂度为O(1)”。实际上,这种表述是不准确的。数组是适合查找操作,但是查找的时间复杂度并...
  • 数组的下标为什么0开始

    千次阅读 2019-01-12 14:11:34
    从数组存储的内存模型上来看,“下标”最确切的定义应该是“偏移(offset)”。如果用a来表示数组的首地址,a[0]就是偏移为0的位置,也就是首地址,a[k]就表示偏移k个type_size的位置,所以计算a[k]的内存地址只需要...
  • 大家学习c语言刚接触数组时候,书上说第一个数组元素要下标0开始数起,不能从1开始数,比如 int a[4]={1,2,3,4}; 那么a[0]=1; 为什么不1数起呢 即a{1}=1呢?不更符合大家的生活习惯吗?
  • 关于Python中数组-1的用法

    万次阅读 多人点赞 2019-03-04 02:43:12
    一个数组a=[0,1,2,3,4],a[-1]表示数组中最后一位,a[:-1]表示第0位开始直到最后一位,a[::-1]表示倒序,最后一位到第0位。 a = [0,1,2,3,4] print(a[-1]) >>4 print(a[:-1]) >&gt...
  • JQ数组操作(定义一个数组,给数组赋值)

    万次阅读 多人点赞 2016-07-14 13:36:33
    JQ数组操作(定义一个数组,给数组赋值)1、JS定义一个数组:(1)、var select=[]; (2)、var select=new Array();2、JS给一个数组赋值:(1)、select.push(); 具体详解: js中添加数组用push.示例如下: var arr = []; ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,477,664
精华内容 591,065
关键字:

如何让数组从1开始