当前位置 博文首页 > 详解Java数组结构_学写作的丧失的博客:java数组的结构

    详解Java数组结构_学写作的丧失的博客:java数组的结构

    作者:[db:作者] 时间:2021-07-19 16:28

    文章导读

    【前面介绍的数据类型都是基本数据类型,例如整型、字符型、浮点型等数据,属于简单的数据类型。但要解决现实问题仅有简单数据类型是不够的,难以反映出现实数据的特点,因此需要提供一类结构化数据以满足数据处理要求。本篇文章主要讲述数组结构,内容包括一维数组和二维数组,以及数组的具体应用】

    本文内容分为五个小节,第一小节讲述最简单的数据结构线性表,以及线性表与数组的关系;第二小节讲述数组的存储结构;第三小节讲述数组的维数;第四小节讲述一维和维数组的声明、初始化和使用方法;第五小节讲述数组元素的访问方法。

    第一小节 线性表与数组

    从详解Java数据及数据类型一文中两个示例可以看出,被计算机加工的数据元素(如:一本书的信息,企业的组织结构等)都不是孤立的,在它们之间存在着某种联系,这种相互之间的关系,通常称做结构。从集合论观点看,结构是一个二元组

    数据结构 = (D,R)

    其中:D是数据元素的集合,R是D上关系的集合。例如,复数可被定义为一种数据结构

    Complex = (D,R)

    其中 D = {x|x是实数}

    R = {R1}

    R1 = {|x,y∈D,x称为实部,y称为序部}

    由此,由任何一对实数均可得到一个复数。又如,整数、实数也是数据结构,由于它们的数据元素间的关系都很简单,称它们为初等数据结构。

    在现实中经常遇到的一种结构是线性表,线性表是最常用而且是最简单的一种数据结构。一个线性表是n个数据元素的有限序列

    (a1,a2,…an)

    至于一个数据元素a的具体含义,在不同的情况下可以不同,它可以是一个整数、也可以是一个浮点数、或者是一个字符、也可以是图书信息、甚至是其它更复杂的信息。

    例如:英文字母表

    (A,B,C,……,Z)

    是一个线性表,表中的数据元素是单个字母。又如,某班级学生数学成绩可以用线性表的形式给出

    (87.5,91,83.2,……,79)

    表中的数据元素是浮点数。

    线性表在物理存储上也分为顺序存储结构和链式存储结构。采用顺序存储结构的线性表也称为数组,其所占的内存区域是连续的;采用链式存储结构的称为链表,链表根据链接形式的不同又分为单链表、双向链表等多种结构。本文主要介绍数组结构。

    第二小节 数组的存储结构

    数组是有序数据的集合,其结构的最大特征就是通过有序编号固定集合内每个数据的位置。有序编号被称为下标,被固定的每个数据被称为元素。数组内所包含元素的数据类型没有限制,可以是任意类型的数据,如数值、字符串、布尔型、对象、数组。下标值是一个从0开始的连续正整数。如下图的0、1、2、length-2、length-1为数组元素的下标,其中length是数组包含元素的个数,length-2为数组倒数第二个元素,length-1为数组最后一个元素。程序可以通过下标访问数组中的元素。其逻辑结构如下图所示。

    图1 数组的逻辑结构

    数组的所有元素在内存中连续存储,其所有元素的数据类型必须相同。不能将数据类型不同的数据存储在同一个数组中。不管数组中含有多少个元素,该数组都将只有一个名称。数组的大小或长度是可容纳元素的最大数量。在数组的处理过程中,如果数组的下标值超过此大小,将会导致程序运行过程中发生不可预知的结果,因此在使用数组时,必须确保数组容纳元素的数量不能超过数组规定的大小。

    下图显示了数组中涉及的概念,包括数组的名称、大小、数组中的元素及数组的下标。

    图2 数组物理结构

    上图显示了名称为Rate的数组及其四个元素,数组名称后面方括号中的数字是数组可容纳元素的最大数量,也称为数组的长度,数组的小标标明了元素在数组中的位置。

    第三小节 数组的维度

    前面介绍的数组结构都是多行单列数据结构,行数为数组的长度,列为数组中的元素。如上节图9-2所示的Rate数组有四行一列,因此其数组长度为4,列元素分别为1.5、3.2、0.09、36.5。结构如下图所示:

    图3 一维数组数据结构

    多行单列的数组结构也可以用表格来表示,上图的数组结构就可以用4行1列的表格来表示:

    类似于图3的数据结构,我们称之为一维数组,一维数组中只有一列数据,数据可以通过下标获取,下标为0的是1.5,下标为1的是3.2,下标为2的是0.09,下标为3的是36.5。

    在用程序解决实际问题中,经常会遇到类似下面问题。例如,有50名学员,现在需要存储每名学员的序号和两门课程的成绩。数据结构可用如下表格所示:

    表格结构为50行3列结构,要存储类似上面表格结构的数据,用前面介绍的一维数组不能满足存储要求。因为一维数组只能存储1列数据,现在有3列数据。用什么数据结构存储上述表格的数据呢?试想一下,如果一维数组的每个元素本身也是一维数组,就可以存储上述表格数据,数据结构如下图所示:

    图 4 二维数组数据结构

    上图所示的数据结构中,Students为数组的名称,数组的长度为50,其数组元素本身也是一个长度为3的数组,该数组有三个元素,分别对应学员序号、语文成绩、数学成绩,其中下标0对应学员序号,下标1对应语文成绩,下标2对应数学成绩。这样就可以根据第一个数组和第二个数组的下标访问一个学员的学号、语文、成绩。例如:如果需要访问学员2的数学成绩,可以通过Students[1][2]来访问学员2的数学成绩,Students[1][2]是访问数组的语法,后面一节会有讲述;再如,如果需要访问学员50的语文成绩,可以通过Students[49][1]来访问学员50的语文成绩。

    类似于上面的数据结构,我们称之为二维数组,二维数组本质上是以数组作为数组元素的数组,访问二维数组的元素时,需要同时给出第一个数组的小标和第二个数组的下标。

    进一步考虑,在上述例子中,如果学员的语文和数学成绩按学期来进行存储,其数据结构可用如下表格所示:

    上面的表格结构为50行3列结构,但在语文和数学列单元中又嵌套了一个3行1列的子表,二维数组无法存储上面的表格数据。如果把语文和数学列单元的数据也用一个数组表示,就可以满足上述表格数据存储要求了,其数据结构如下图所示:

    图5 三维数组数据结构

    上图所示的数据结构中,Students为数组的名称,数组的长度为n,其数组元素本身也是一个长度为3的数组,该数组有三个元素,分别对应学员序号、语文成绩、数学成绩,其中语文成绩和数学成绩元素本是也是一个数组,该数组长度为n,记录了n个学期的考试成绩。这样就可以根据第一个数组、第二个数组的下标访问一个学员的学号,根据第一个数组、第二个数组和第三个数组的下标访问学员的学期成绩。例如:如果需要访问第一个学员的学员学号,可以通过Students[0][0]来访问第一个学员的学员学号;访问第一个学员语文第一学期的成绩,可以通过Students[0][1][0]来访问;访问第一个学员语文第n学期的成绩,可以通过Students[0][1][n]来访问。

    类似于上面存储语文和数学学期成绩的数据结构,我们称之为三维数组,三维数组本质上是三层数组的嵌套,分为第一层数组、第二层数组、第三层数组。第一层数组的元素是第二层数组,第二层数组的元素是第三层数组。访问三维数组的元素时,需要同时给出三个数组的下标。

    可以类推,数组的数据结构可有四维数组、甚至更多维数组,随着数组维数的增多,其数据存储复杂度和计算复杂度也相应提升。在编程应用中,一般常用的为一维数组、二维数组和三维数组。

    第四小节 一维数组与二维数组

    在数组应用中,最常用的就是一维数组和二维数组。一维数组只有一个小标,二维数组有两个小标。

    声明一维数组的语法为

    类型说明符 数组名[];

    其中类型说明符可以是Java语言中任何有效的数据类型,如int、float、char等。数组名是引用数组的名称,数组名的命名需符合变量命名规则。

    例如:

    int a[];

    //定义了一个数组,名称为a,数组中的元素类型是int

    float score[];

    //定义了一个数组,名称为float,数组中的元素类型是float

    声明二维数组的语法为

    类型说明符 数组名[][];

    例如:

    int a[][];

    double score[][];

    其中,声明语句的第一个方括号可以称为行数组,第二个方括号可以称为列数组。

    声明了一个数组,只是得到了一个存放数组的地址变量,并没有为数组元素分配内存空间,因而不能直接使用,必须经过初始化,为数组分配内存空间才能使用。

    数组的初始化有两种方法,一种是静态初始化,另一种是动态初始化。

    一维数组的静态初始化

    在声明数组时,直接给数组的每个元素赋上一个初始值。静态初始化一般在数组元素比较少时使用。

    静态初始化的语法为:

    数组类型 数组名[]={值1, 值2,……, 值2};

    例如:

    int a[] = {26,67,89,106,210};

    float score[] = {87.5,67.2,96.8,92.6,75.9};

    char chArray[] = {‘a’,’m’,’o’,’p’,’q’};

    对于数组a,可以看出数组中有5个元素,分别是a[0]、a[1]、a[2]、a[3]、a[4]、a[5],即数组下标从0开始,这5个元素的数值依次为a[0]=26、a[1]=67、a[2]=89、a[3]=106、a[4]=210。其在内存中结构如下图所示:

    图6 a数组在内存中的存储结构

    错误的初始化:

    int a[];

    a[] = {26,67,89,106,210};

    数组的初始化只能在声明中完成,不能声明完成后,再进行初始化。

    二维数组的静态初始化

    静态初始化是在数组声明时,对声明的数组元素赋初值的过程。

    例如:

    int array[][] = {{3,-9,6},{8,0,1},{11,9,8}};

    声明并初始化数组array,它有3个元素,每个元素又都是有3个元素的一维数组。外层大括号对里面的元素是行数组的元素,因为行数组元素是一维数组,因此每个行数组元素也用大括号对包括起来,里面的元素是列数组的元素。

    另外,用指定初值的方式对数组进行初始化时,列数组元素的个数可以不同。

    例如:

    int array[][] = {{3,6},{8,0,1},{11,9,8}};

    此时,第一个列数组的元素个数是2,第二个和第三个列数组的元素个数是3个。

    一维数组的动态初始化

    有时,数组并不需要在声明时就赋初值,而是在使用时才进行赋值。另外,有些数组比较大,元素非常多,用静态初始化不方便,这样就需要使用动态初始化。数组的动态初始化使用new操作符。

    动态初始化的方式有两种。

    ● 先声明数组,再用new分配内存

    例如:

    int a[];

    a = new int[4];

    Java的new运算操作符,用来在内存中申请存储空间,并将申请到存储空间的首地址赋值给被申请的变量。语句a = new int[4]为数组a分配了4个元素,这4个元素分别是a[0]、a[1]、a[2]、a[3],它们的值都为0。

    ● 在定义数组的同时用new分配内存

    例如:

    int a[] = new int[4];

    int size = 100;

    //也可以用变量给出数组的大小

    float score[] = new float[size];

    二维数组的动态初始化

    二维数组的动态初始化同一维数组相同,也是先声明数组,然后通过new运算符分配内存。语法格式为:

    类型说明符 数组名[][] = new 类型说明符[数组长度][];

    或:

    类型说明符 数组名[][] = new 类型说明符[数组长度][ 数组长度];

    例如:

    int array[][];

    array = new int[3][];

    array = new int[3][3];

    第五小节 数组元素的访问

    使用数组的最基本操作是数组元素的访问,对数组的使用最终都通过对元素的使用而实现。数组的元素通过数组下标进行访问。前面已经讲过,在Java语言中,数组下标是从0开始的,所以包含n个元素的数组下标的范围是0到n-1。例如:前面定义的数组a,其下标范围为0到4。要访问a数组的元素,可通过a[0]、a[1]、a[2]、a[3]、a[4]访问a数组的各个元素,此时,方括号中的数字是数组的下标,表示访问数组的第几个元素。

    二维数组的元素通过两个下标进行访问,分别是行数组下标和列数组下标,例如:对于二维数组a,可通过a[i][j]进行访问,其中i和j为数组a的下标。二维数组行数组的长度可通过a.length获取,列数组的长度可通过a[i]. length获取。

    例如:

    int a[][] = {{3,-9,6},{8,0,1},{11,9,8}};

    int i,j;

    for( i = 0; i < a.length; i++ )

    {

    for(j=0; j

    System.out.printf("a[ %d][%d] 数组元素的值为: %d;\n",i,ja[i][j]);

    }

    在遍历数组的外层for循环中,循环条件为a.length,a.length就是行数组长度的值,在内层for循环中,循环条件为a[i]. length,a[i]. length为当前行数组第i个元素数组的长度。

    文章小结

    1、数组是Java语言中一种简单且重要的数据结构,是具有相同的数据类型且按一定次序排列的一组数据的集合体。数组有一个统一的名称,通过名称和数组下标可以访问数组中的任意元素。

    2、对数组的访问一般是通过下标进行的。在一维数组中,数组的下标是由一个数字构成的,通过这一个数字组成的下标对数组的内容进行访问;在二维数组中,数组的下标是由两个数字构成的,通过这两个数字组成的下标对数组的内容进行访问;在三维数组中,数组的下标是由三个数字构成的,通过这三个数字组成的下标对数组的内容进行访问。

    3、可以把一维数组看作超市商品货柜中一列存放同类商品的格子,商家如果要把商品放到格子中,需要提前向超市申请格子的使用权,超市同意使用后,商家才能把商品放到格子中,然后根据格子的编号存取商品。再回到编程中来,程序要使用一维数组,必须要向计算机操作系统申请数组的使用权以及使用空间大小,操作系统分配给数组存储空间后,程序方可使用。因此,数组在使用中必须先声明并初始化后才能使用,声明和初始化数组的目的是为其留出所需要的存储空间,用来存储数组元素。

    4、二维数组用于描述多行多列的数据结构。例如:超市的商品货柜可以用二维数组进行描述,商品货柜是由多行和多列组成的网格,商品货柜的行号和列号可以确定唯一的格子单元;再如:学校教室课桌的安排也是多行多列的数据结构,课桌的位置由课桌所在的行数和课桌所在的列数确定。

    cs