一、多维数组的定义
当一维数组元素的类型也是一维数组时,便构成了二维数组。二维数组定义的一般格式:
array[下标类型1] of array[下标类型2] of 元素类型;
但我们一般这样定义二维数组:
array[下标类型1,下标类型2] of 元素类型;
说明:其中两个下标类型与一维数组定义一样,可以看成"下界1..上界1"和"下界2..上界2",给出二维数组中每个元素( 双下标变量)可以使用下标值的范围。of后面的元素类型就是基类型。
一般地,n维数组的格式为:
array[下标类型1,下标类型2,…,下标类型n] of 元素类型;
其中,下标类型的个数即数组的维数,且说明了每个下标的类型及取值范围。
二、多维数组元素的引用
多维数组的数组元素引用与一维数组元素引用类似,区别在于多维数组元素的引用必须给出多个下标,引用的格式为:
<数组名>[下标1,下标2,…,下标n]
说明:显然,每个下标表达式的类型应与对应的下标类型一致,且取值不超出下标类型所指定的范围;例如,设有说明:
type matrix=array[1..5,1..4]of integer;
var a:matrix;
则表示a是二维数组,共有5*4=20个元素,它们是:
a[1,1]a[1,2]a[1,3]a[1,4]
a[2,1]a[2,2]a[2,3]a[2,4]
a[3,1]a[3,2]a[3,3]a[3,4]
a[4,1]a[4,2]a[4,3]a[4,4]
a[5,1]a[5,2]a[5,3]a[5,4]
因此可以看成一个矩阵,a[4,2]即表示第4行、第2列的元素。由于计算机的存储器是一维的,要把二维数组的元素存放到存储器中,pascal是按行(第一个下标)的次序存放,即按a[1,1]a[1,2]a[1,3]a[1,4]a[2,1]…a[5,4]的次序存放于存储器中某一组连续的存储单元之内。
对于整个二维数组的元素引用时,大多采用二重循环来实现。如:给如上说明的二维数组a进行赋值:a[i,j]=i*j
for i:=1 to 5 do
for j:=1 to 4 do
a[i,j]:=i*j;
对二维数组的输入与输出也同样可用二重循环来实现:
for i:=1 to 5 do
begin
for j:=1 to 4 do
read(a[i,j]);
readln;
end;
for i:=1 to 5 do
begin
for j:=1 to 4 do
write(a[i,j]:5);
writeln;
end;
三、多维数组的应用示例
【例1】设有一程序:
program ex5_3;
const n=3;
type matrix=array[1..n,1..n]of integer;
var a:matrix;
i,j:1..n;
begin
for i:=1 to n do
begin
for j:=1 to n do read(a[i,j]);
readln;
end;
for i:=1 to n do
begin
for j:=1 to n do write(a[j,i]:5);
writeln;
end;
end.
且运行程序时的输入为:
2□1□3←┘
3□3□1←┘
1□2□1←┘
则程序的输出应是:
2□3□1
1□3□2
3□1□1
【例2】输入4名学生数学、物理、英语、化学、pascal五门课的考试成绩,求出每名学生的平均分,打印出表格。
分析:用二维数组a存放所给数据,第一下标表示学生的学号, 第二个下标表示该学生某科成绩,如a[i,1]、a[i,2]、a[i,3]、a[i,4]、a[i,5]分别存放第i号学生数学、物理、英语、化学、pascal 五门课的考试成绩,由于要求每个学生的总分和平均分, 所以第二下标可多开两列,分别存放每个学生5门成绩和总分、平均分。
源程序如下:
program ex5_4;
var a:array[1..4,1..7]of real;
i,j:integer;
begin
fillchar(a,sizeof(a),0);
{函数fillchar用以将a中所有元素置为0}
writeln("Enter 4 students score");
for i:=1 to 4 do
begin
for j:=1 to 5 do {读入每个人5科成绩}
begin
read(a[i,j]);
{读每科成绩时同时统计总分}
a[i,6]:=a[i,6]+a[i,j];
end;
readln;
a[i,7]:=a[i,6]/5;{求平均分}
end;
{输出成绩表}
writeln( "No. Mat. Phy. Eng. Che. Pas. Tot. Ave.");
for i:=1 to 4 do
begin
write(i:2," ");
for j:=1 to 7 do
write(a[i,j]:9:2);
writeln;
end;
end.
四、数组类型的应用
【例3】输入一串字符,字符个数不超过100,且以"·"结束,判断它们是否构成回文
分析:所谓回文指从左到右和从右到左读一串字符的值是一样的,如12321、ABCBA、AA等;先读入要判断的一串字符(放入数组letter中),并记住这串字符的长度,然后首尾字符比较,并不断向中间靠拢,就可以判断出是否为回文。
源程序如下:
program ex5_5;
var
letter:array[1..100] of char;
i,j:0..100;
ch:char;
begin
{读入一个字符串以"."号结束}
write("Input a string:");
i:=0;read(ch);
while ch<>"." do
begin
i:=i+1;letter[i]:=ch;
read(ch)
end;
{判断它是否是回文}
j:=1;
while (j<i)and(letter[j]=letter[i])do
begin
i:=i-1;j:=j+1;
end;
if j>=i then writeln("Yes.")
else writeln("No.");
end.
【例4】奇数阶魔阵
魔阵是用自然数1、2、3…、n2填n阶方阵的各个元素位置,使方阵的每行的元素之和、每列元素之和及主对角线元素之和均相等;奇数阶魔阵的一个算法是将自然数数列从方阵的中间一行最后一个位置排起,每次总是向右下角排(即A[i,j]的下一个是A[i+1,j+1]),但若遇以下四种情形,则应修正排数法。
(1)、列排完(即j=n+1时),则转排第一列
(2)、行排完(即i=n+1时),则转排第一行
(3)、对A[n,n]的下一个总是A[n,n-1]
(4)、若A[i,j]已排进一个自然数,则排A[i-1,j-2]
例如3阶方阵,则按上述算法可排成:
4 3 8
9 5 1
2 7 6
有了以上的算法,解题主要思路可用伪代码描述如下:
1 i :=n div 2+1,y :=n /*排数的初始位置*/
2 a[i,j] :=1;
3 for k:=2 to n*n do
4 计算下一个排数位置 (i,j)
5 if a[i,j]<>0 then
6 i :=i-1;
7 j :=j-2;
8 a[i,j] :=k;
9 endfor
对于计算下一个排数位置,按上述的四种情形进行,但我们应先处理第三处情况。算法描述如下:
1 if (i=n)and(j=n) then
2 j :=j-1; /*下一个位置为(n,n-1)*/;
3 else
4 i :=i mod n +1;
5 j :=j mod n +1;
6 endif;
源程序如下:
program ex5_7;
var
a : array[1..99,1..99]of integer;
i,j,k,n : integer;
begin
fillchar(a,sizeof(a),0);
write("n=");readln(n);
i:=n div 2+1;j:=n;
a[i,j]:=1;
for k:=2 to n*n do
begin
if (i=n)and(j=n) then
j:=j-1
else
begin
i:=i mod n +1;
j:=j mod n +1;
end;
if a[i,j]<>0 then
begin
i:=i-1;
j:=j-2;
end;
a[i,j]:=k;
end;
for i:=1 to n do
begin
for j:=1 to n do
write(a[i,j]:5);
writeln;
end;
end.
练习:
1.定义一个10×10的二维数组,将每个元素的值设为其行列值之和,并将结果输出到屏幕上(10行10列,尽量工整)
2.输入一个正整数N(N<=80),定义一个N行N列的二维数组,将这个二维数组对应矩阵的两条对角线上的元素都赋值为字符“+”,其余元素赋值为字符“-”,并将最后的结果工整的输出到屏幕上,如:
N=5
+ - - - +
- + - + -
- - + - -
- + - + -
+ - - - +
3.输入N个同学的语、数、英三科成绩,计算他们的总分与平均分,并统计出每个同学的名次,最后以表格的形式输出。
4.输出杨辉三角的前N行(N<10)。
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
5.构造“N阶魔方阵”,所谓“N阶魔方阵”是指这样的方阵:它的每一行、每一列和对角线之和均相等;如,三阶魔方阵为
8 1 6
3 5 7
4 9 2
6.找出一个二维数组的鞍点,即该位置上的元素在该行上最大、该列上最小,也可能没有鞍点。数组的值从键盘输入,如:
19 23 21 13
61 25 34 45
67 32 39 29
39 98 27 56
如果没有鞍点则显示NO!,有则显示每个鞍点的位置和值,一个占一行