数组的定义和特点
数组: 按一定格式排列起来的,具有相同类型的数据元素的集合。
一维数组: 若线性表中的数据元素为非结构的简单元素。它的逻辑结构是线性结构,定长的线性表。格式为:数据类型 变量名[长度]。
二维数组: 若一维数组中的数据元素又是一维数组结构,则称为二维数组,其逻辑结构为,
二
维
数
组
的
逻
辑
结
构
{
非
线
性
结
构
            
每
一
个
数
据
元
素
即
在
一
个
行
表
中
也
在
一
个
列
表
中
。
线
性
结
构
(
定
长
的
线
性
表
)
            
该
线
性
表
的
每
一
个
数
据
元
素
也
是
一
个
定
长
的
线
性
表
。
二维数组的逻辑结构\left\{ {\begin{array}{l} {非线性结构\;\;\;\;\;\;每一个数据元素即在一个行表中也在一个列表中。}\\ {线性结构(定长的线性表)\;\;\;\;\;\;该线性表的每一个数据元素也是一个定长的线性表。} \end{array}} \right.
二维数组的逻辑结构{非线性结构每一个数据元素即在一个行表中也在一个列表中。线性结构(定长的线性表)该线性表的每一个数据元素也是一个定长的线性表。
声明格式:数据类型 变量名称[行数][列数]。
在定义二维数组类型时,也可以这样定义,
typedef int array1[4]; //列数
typedef array1 array2[2]; //行数
定义了一个int类型的二维数组,行数是2,列数是4。
示例程序如下:
#include "stdafx.h"
#include<iostream>
using namespace std;
typedef int array1[4]; //列数
typedef array1 array2[2]; //行数
int main()
{
array2 ar;
for(int i=0;i<2;++i)
for (int j = 0; j < 4; ++j)
{
ar[i][j] = 4 * i + j + 1;
}
for (int i = 0; i<2; ++i)
for (int j = 0; j < 4; ++j)
cout << ar[i][j] << endl;
}
n维数组: 若n-1维数组中的元素又是一个一维数组结构。
数组与线性表的关系:
- 线性表是数组结构中的一个特例。
- 数组结构是线性表结构的扩展。
数组特点:结构固定——定义后,维数和维界不再改变。
数组的基本操作:除了结构的初始化和销毁外,一般只有取元素和修改元素值的操作。
数组的抽象类型定义
n维数组的抽象类型:
ADT Array
{
数据对象:
j
i
=
0
,
.
.
.
,
b
i
−
1
      
i
=
1
,
2
,
.
.
.
,
n
    
这
里
的
n
为
数
组
的
维
数
,
b
i
为
数
组
第
i
维
的
长
度
,
j
i
表
示
数
组
元
素
第
i
维
的
下
标
D
=
{
a
j
1
j
2
.
.
.
j
n
∣
a
j
1
j
2
.
.
.
j
n
∈
E
l
e
m
S
e
t
}
j_i=0,...,b_i-1\;\;\;i=1,2,...,n\;\;这里的n为数组的维数,b_i为数组第i维的长度,j_i表示数组元素第i维的下标 \\D=\{a_{j_1j_2...j_n }|a_{j_1j_2...j_n}\in ElemSet \}
ji=0,...,bi−1i=1,2,...,n这里的n为数组的维数,bi为数组第i维的长度,ji表示数组元素第i维的下标D={aj1j2...jn∣aj1j2...jn∈ElemSet}
数据关系:
R
=
{
<
a
j
1
.
.
.
j
i
.
.
.
j
n
,
a
j
1
.
.
.
j
i
+
1...
j
n
>
∣
0
≤
j
k
≤
b
k
−
1
,
1
≤
k
≤
n
,
且
k
≠
i
,
0
≤
j
i
≤
b
k
−
2
,
a
j
1
.
.
.
j
i
.
.
.
j
n
,
a
j
1
.
.
.
j
i
+
1...
j
n
∈
D
,
i
=
1
,
2
,
.
.
.
,
n
}
R=\{<a_{j_1...j_i...j_n},a_{j_1...j_i+1...j_n}>|0 \le {j_k} \le {b_k} - 1,1 \le k \le n,且k \ne i,0 \le {j_i} \le {b_k} - 2,a_{j_1...j_i...j_n},a_{j_1...j_i+1...j_n} \in D,i=1,2,...,n\}
R={<aj1...ji...jn,aj1...ji+1...jn>∣0≤jk≤bk−1,1≤k≤n,且k̸=i,0≤ji≤bk−2,aj1...ji...jn,aj1...ji+1...jn∈D,i=1,2,...,n}
基本操作:
(1) InitArray(&A,n,bound1,…,boundn) //构造数组A
(2) DestroyArray(&A) //销毁数组A
(3) Value(A,&e,index1,…,indexn) //取数组元素的值
(4) Assign(A,&e,index1,…,indexn) //给数组元素赋值
}ADT Array
以二维数组为例:
n=2(维数为2,代表二维数组)
b
1
b_1
b1:第1维长度(行数)
b
2
b_2
b2:第2维长度(列数)
a
j
1
j
2
a_{j_1j_2}
aj1j2:第1维下标为
j
1
j_1
j1,第2维下标为
j
2
j_2
j2.
[ a 00 a 01 ⋯ a 0 ( b 2 − 1 ) a 10 a 11 ⋯ a 1 ( b 2 − 1 ) ⋮ ⋮ a j 1 j 2 ⋮ a ( b 1 − 1 ) 0 a ( b 1 − 1 ) 1 ⋯ a ( b 1 − 1 ) ( b 2 − 1 ) ] \left[ {\begin{array}{} {{a_{00}}}&{{a_{01}}}& \cdots &{{a_{0({b_2} - 1)}}}\\ {{a_{10}}}&{{a_{11}}}& \cdots &{{a_{1({b_2} - 1)}}}\\ \vdots & \vdots &{{a_{{j_1}{j_2}}}}& \vdots \\ {{a_{({b_1} - 1)0}}}&{{a_{({b_1} - 1)1}}}& \cdots &{{a_{({b_1} - 1)({b_2} - 1)}}} \end{array}} \right] ⎣⎢⎢⎢⎡a00a10⋮a(b1−1)0a01a11⋮a(b1−1)1⋯⋯aj1j2⋯a0(b2−1)a1(b2−1)⋮a(b1−1)(b2−1)⎦⎥⎥⎥⎤
二维数组的抽象类型为:
- 数据对象:
D = { a j 1 j 2 ∣ 0 ≤ j 1 ≤ b 1 − 1 , 0 ≤ j 2 ≤ b 2 − 1 } D = \{ {a_{{j_1}{j_2}}}|0 \le {j_1} \le {b_1} - 1,0 \le {j_2} \le {b_2} - 1\} D={aj1j2∣0≤j1≤b1−1,0≤j2≤b2−1} - 数据关系:
R = ( R O W , C O L ) R O W = { < a j 1 j 2 , a j 1 + 1 j 2 > ∣ 0 ≤ j 1 ≤ b 1 − 2 0 ≤ j 2 ≤ b 2 − 1 } C O L = { < a j 1 j 2 , a j 1 ( j 2 + 1 ) > ∣ 0 ≤ j 1 ≤ b 1 − 1 0 ≤ j 2 ≤ b 2 − 2 } \begin{array}{l} R = (ROW,COL)\\ ROW = \{ < {a_{{j_1}{j_2}}},{a_{{j_1}{\rm{ + 1}}{j_2}}} > |0 \le {j_1} \le {b_{\rm{1}}}{\rm{ - 2}}0 \le {j_{\rm{2}}} \le {b_{\rm{2}}}{\rm{ - 1}}\} \\ COL = \{ < {a_{{j_1}{j_2}}},{a_{{j_1}({j_2} + 1)}} > |0 \le {j_1} \le {b_{\rm{1}}}{\rm{ - 1}}0 \le {j_{\rm{2}}} \le {b_{\rm{2}}}{\rm{ - 2}}\} \end{array} R=(ROW,COL)ROW={<aj1j2,aj1+1j2>∣0≤j1≤b1−20≤j2≤b2−1}COL={<aj1j2,aj1(j2+1)>∣0≤j1≤b1−10≤j2≤b2−2}
数组的顺序存储
一般用顺序存储结构来表示数组,因为数组特点是结构固定的,即维数和维界是不变的,另外,一般不对数组进行插入和删除的操作。
既然是顺序存储,就会带来一个问题。
数组是多维的,而存储数据元素的内存单元是一维的,所以,在存储数组结构之前,需要解决从多维关系映射到一维关系的问题。下面就来具体讨论,
- 一维数组
例如,有数组定义:int a[5];
,每个元素占4个字节,假设a[0]存储在2000单元,a[3]的地址是多少?
示意图如上图,LOC[3]=LOC[0]+4*3=2012.
如果用L表示每个元素存储所占用的字节数,a表示第一个元素的地址,则第i个元素的位置为,
L
O
C
(
i
)
=
{
L
O
C
(
0
)
=
a
,
                                                            
i
=
0
L
O
C
(
i
−
1
)
+
L
=
a
+
i
∗
L
,
            
i
>
0
LOC(i) = \left\{ {\begin{array}{l} {LOC(0) = a,\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;i = 0}\\ {LOC(i - 1) + L = a + i*L,\;\;\;\;\;\;i > 0} \end{array}} \right.
LOC(i)={LOC(0)=a,i=0LOC(i−1)+L=a+i∗L,i>0
- 二维数组
二维数组可以看成由若干个一维数组构成的,有两种看待方式:-
由若干行组成,每一行都是一个一维数组——行主序
A = ( α 1 , α 2 , ⋯   , α m ) α i = ( a i 1 , a i 2 , ⋯   , a i n )        1 ≤ i ≤ m \begin{array}{l} A = ({\alpha _1},{\alpha _2}, \cdots ,{\alpha _m})\\ {\alpha _i} = ({a_{i1}},{a_{i2}}, \cdots ,{a_{in}})\;\;\;1 \le i \le m \end{array} A=(α1,α2,⋯,αm)αi=(ai1,ai2,⋯,ain)1≤i≤m
示意图如下,
A m × n = [ [ a 11 a 12 ⋯ a 1 n ] [ a 21 a 22 ⋯ a 2 n ] ⋮ [ a m 1 a m 2 ⋯ a m n ] ] {A_{m \times n}} = \left[ {\begin{array}{} {\left[ {\begin{array}{} {{a_{11}}}&{{a_{12}}}& \cdots &{{a_{1n}}} \end{array}} \right]}\\ {\left[ {\begin{array}{} {{a_{21}}}&{{a_{22}}}& \cdots &{{a_{2n}}} \end{array}} \right]}\\ \vdots \\ {\left[ {\begin{array}{} {{a_{m1}}}&{{a_{m2}}}& \cdots &{{a_{mn}}} \end{array}} \right]} \end{array}} \right] Am×n=⎣⎢⎢⎢⎡[a11a12⋯a1n][a21a22⋯a2n]⋮[am1am2⋯amn]⎦⎥⎥⎥⎤
-
由若干列组成,每一列都是一个一维数组——列主序
A = ( α 1 , α 2 , ⋯   , α n ) α j = ( a 1 j , a 2 j , ⋯   , a m j )        1 ≤ j ≤ n \begin{array}{l} A = ({\alpha _1},{\alpha _2}, \cdots ,{\alpha _n})\\ {\alpha _j} = ({a_{1j}},{a_{2j}}, \cdots ,{a_{mj}})\;\;\;1 \le j \le n \end{array} A=(α1,α2,⋯,αn)αj=(a1j,a2j,⋯,amj)1≤j≤n
示意图如下,
A m × n = [ [ a 11 a 21 ⋮ a m 1 ] [ a 12 a 22 ⋮ a m 2 ] ⋯ [ a 1 n a 2 n ⋮ a m n ] ] {A_{m \times n}} = \left[ {\begin{array}{} {\left[ {\begin{array}{} {{a_{11}}}\\ {{a_{21}}}\\ \vdots \\ {{a_{m1}}} \end{array}} \right]}&{\left[ {\begin{array}{} {{a_{12}}}\\ {{a_{22}}}\\ \vdots \\ {{a_{m2}}} \end{array}} \right]}& \cdots &{\left[ {\begin{array}{} {{a_{1n}}}\\ {{a_{2n}}}\\ \vdots \\ {{a_{mn}}} \end{array}} \right]} \end{array}} \right] Am×n=⎣⎢⎢⎢⎡⎣⎢⎢⎢⎡a11a21⋮am1⎦⎥⎥⎥⎤⎣⎢⎢⎢⎡a12a22⋮am2⎦⎥⎥⎥⎤⋯⎣⎢⎢⎢⎡a1na2n⋮amn⎦⎥⎥⎥⎤⎦⎥⎥⎥⎤
-
所以,对于二维数组的顺序存储就有两种存储方式:
{
以
行
序
为
主
序
(
低
下
标
优
先
)
—
—
行
主
序
以
列
序
为
主
序
(
高
下
标
优
先
)
—
—
列
主
序
\left\{ {\begin{array}{} {以行序为主序(低下标优先)——行主序}\\ {以列序为主序(高下标优先)——列主序} \end{array}} \right.
{以行序为主序(低下标优先)——行主序以列序为主序(高下标优先)——列主序
下面重点说明以行序为主序,
有一个二维数组A[m][n]
,设数组的开始的存储位置为LOC(0,0),存储每个元素需要L个存储单元,则数组元素a[i][j]的存储位置为:
L
O
C
(
i
,
j
)
=
L
O
C
(
0
,
0
)
+
(
n
∗
i
+
j
)
∗
L
LOC(i,j)=LOC(0,0)+(n*i+j)*L
LOC(i,j)=LOC(0,0)+(n∗i+j)∗L
上式中, ( n ∗ i + j ) ∗ L (n*i+j)*L (n∗i+j)∗L为a[i][j]前面的元素个数。