第5章〓数组和稀疏矩阵 5.1练习题及参考答案 5.1.1练习题 1. 单项选择题 (1) 有一个三维数组A[-2..2][-4..5][2..6],其元素个数是()。 A. 60B. 250C. 144D. 396 (2) 设二维数组A[1..5][1..8],若按行优先的顺序存放数组的元素,则A[4][6]元素的前面有()个元素。 A. 6B. 28C. 29D. 40 (3) 设二维数组A[1..5][1..8],若按列优先的顺序存放数组的元素,则A[4][6]元素的前面有()个元素。 A. 6B. 28C. 29D. 40 (4) 一个n阶对称矩阵A采用压缩存储方式,将其下三角部分按行优先存储到一维数组B中,则B中元素个数是()。 A. nB. n2 C. n(n+1)/2D. n(n+1)/2+1 (5) 一个n阶对称矩阵A[1..n,1..n]采用压缩存储方式,将其下三角部分按行优先存储到一维数组B[1..m]中,则A[i][j](i≥j)元素在B中的位置k是()。 A. j(j-1)/2+iB. j(j-1)/2+i-1 C. i(i-1)/2+jD. i(i-1)/2+j-1 (6) 一个对称矩阵A[1..10,1..10]采用压缩存储方式,将其下三角部分按行优先存储到一维数组B[0..m]中,则A[8][5]元素在B中的位置k是()。 A. 32B. 37C. 45D. 60 (7) 一个对称矩阵A[1..10,1..10]采用压缩存储方式,将其下三角部分按行优先存储到一维数组B[0..m]中,则A[5][8]元素值在B中的位置k是()。 A. 18B. 32C. 45D. 60 (8) 一个对称矩阵A[1..10,1..10]采用压缩存储方式,将其上三角部分按行优先存储到一维数组B[1..m]中,则A[8][5]元素值在B中的位置k是()。 A. 10B. 37C. 45D. 60 (9) 一个n阶上三角矩阵A按列优先顺序压缩存放在一维数组B,则B中元素个数是()。 A. nB. n2C. n(n+1)/2D. n(n+1)/2+1 (10) 一个10阶下三角矩阵A[0..9,0..9]按行优先压缩存放在一维数组B[0..m]中,则A[3][2]在B中的位置k是()。 A. 1B. 8C. 10D. 21 (11) 对特殊矩阵采用压缩存储的目的主要是()。 A. 使表达变得简单B. 使存取矩阵元素变得简单 C. 去掉矩阵中的多余元素D. 减少不必要的存储空间 (12) 稀疏矩阵是指()的矩阵。 A. 非零元素较多且分布无规律B. 非零元素较少且分布无规律 C. 总元素个数较少D. 不适合用二维数组表示 (13) 稀疏矩阵一般的压缩存储方法有两种,即()。 A. 二维数组和三维数组B. 三元组和散列 C. 三元组和十字链表D. 散列和十字链表 (14) 一个稀疏矩阵采用压缩后,和直接采用二维数组存储相比会失去()特性。 A. 顺序存储B. 随机存取C. 输入输出D. 以上都不对 (15) 一个m行n列的稀疏矩阵采用十字链表表示时,其中总的头结点的个数为()。 A. m+1B. n+1 C. m+n+1D. MAX{m,n}+1 2. 填空题 (1) 三维数组A[c1..d1,c2..d2,c3..d3](c1≤d1,c2≤d2,c3≤d3)共含有()个元素。 (2) 已知二维数组A[m][n]采用行序为主序存储,每个元素占k个存储单元,并且第一个元素的存储地址是LOC(A[0][0]),则A[i][j]的地址是()。 (3) 二维数组A[10][20]采用列序为主序存储,每个元素占一个存储单元,并且A[0][0]的存储地址是200,则A[6][12]的地址是()。 (4) 二维数组A[10..20][5..10]采用行序为主方式存储,每个元素占4个存储单元,并且A[10][5]的存储地址是1000,则A[18][9]的地址是()。 (5) 有一个10阶对称矩阵A,采用压缩存储方式(以行序为主存储下三角部分,且A[0][0]存放在B[1]中),则A[8][5]在B中的地址是()。 (6) 设n阶下三角矩阵A[1..n][1..n]已压缩到一维数组B[1..n(n+1)/2]中,若按行序为主存储,则A[i][j]对应的B中的存储位置是()。 (7) 稀疏矩阵的三元组表示中,每个结点对应于稀疏矩阵的一个非零元素,它包含三个数据项,分别表示该元素的()。 3. 简答题 (1) 简述数组的主要基本运算。 (2) 为什么说数组是线性表的推广或扩展,而不说数组就是一种线性表呢? (3) 为什么数组一般不采用链式结构存储? (4) 如果一维数组A中元素个数n很大,存在大量重复的元素,且所有元素值相同的元素紧挨在一起,请设计一种压缩存储方式使得存储空间更节省。 4. 算法设计题 (1) 假定数组A[0..n-1]的n个元素中有多个零元素,设计一个算法将A中所有的非零元素全部移到A的前端。 (2) 有一个含有n个整数元素的数组a[0..n-1],设计一个算法通过比较求a[i..j]中的第一个最小元素的下标。 (3) 设计一个算法,求一个n×n的二维整型数组A的下三角和主对角部分的所有元素之和。 (4) 设计一个算法,给定一个n×n的二维整型数组A,按位置输出其中左上右下和左下右上两条对角线的元素。 5.1.2练习题参考答案 1. 单项选择题 (1) B(2) C(3) B(4) C(5) C (6) A(7) B(8) B(9) D(10) B (11) D(12) B(13) C(14) B(15) D 2. 填空题 (1) (d1-c1+1)×(d2-c2+1)×(d3-c3+1) (2) LOC(A[0][0])+(n×i+j)×k (3) 326 (4) 1208 (5) 42 (6) i(i-1)/2+j (7) 行下标、列下标和元素值 3. 简答题 (1) 答: 数组的主要基本运算如下。 ① 取值运算: 给定一组下标,读取其对应的数组元素。 ② 赋值运算: 给定一组下标,存储或修改与其相对应的数组元素。 (2) 答: 从逻辑结构的角度看,一维数组是一种线性表; 二维数组可以看成数组元素为一维数组的一维数组,所以二维数组是线性结构,可以看成是线性表,但就二维数组的形状而言,它又是非线性结构,因此将二维数组看成是线性表的推广更准确。三维及以上维的数组也是如此。 (3) 答: 因为数组使用链式结构存储时需要额外占用更多的存储空间,而且不具有随机存取特性,使得相关操作更复杂。 (4) 答: 设数组的元素类型为ElemType,采用一种结构体数组B来实现压缩存储,该结构体数组的元素类型如下。 struct {ElemType data;//元素值 int length;//重复元素的个数 } 如数组A[]={1,1,1,5,5,5,5,3,3,3,3,4,4,4,4,4,4},共有17个元素,对应的压缩存储B如下。 {{1,3},{5,4},{3,4},{4,6}} 压缩数组B中仅有8个整数。从中看出,如果重复元素越多,采用这种压缩存储方式越节省存储空间。 4. 算法设计题 (1) 解: 从前向后找为零的元素A[i],从后向前找非零的元素A[j],将A[i]和A[j]进行交换。对应的算法如下。 void move(ElemType A[],int n) {int i=0,j=n-1; ElemType tmp; while (i=n || i>j || j>=n) return 0;//参数错误返回0 mini=i; for (k=i+1;k<=j;k++) {if (a[k] #define M 10 #define N 10 int Prenums1(int m,int n,int i,int j)//以行序为主序 {int k; if (i>=0 && i=0 && j=0 && i=0 && jj,它的元素值等于aj,i。 归纳起来,对于对称矩阵A={ai,j}中的任何元素,在B数组中下标k的关系如下。 k=j(j+1)/2+i当i≤j k=i(i+1)/2+j当i>j 对应的实验程序如下。 #include #define N 4 int findk(int i,int j)//由i,j求k {if (i<=j) return(j*(j+1)/2+i); else return(i*(i+1)/2+j); } int Compress(int A[N][N],int B[])//将A压缩存储到B中 {int i,j,k=0; for (j=0;j void Trans(int a[],int n)//转换算法 {int i,j,c; for (i=n-1;i>=0;i--) {c=0; for (j=0;j void Reverse(int A[],int i,int j)//逆置A[i..j] {int k,tmp; for (k=0;k<(j-i+1)/2;k++) {tmp=A[i+k]; A[i+k]=A[j-k]; A[j-k]=tmp; } } void Rightmove(int A[],int n,int m)//将A[0..n-1]循环右移m个元素 {if (m>n) m=m%n; Reverse(A,0,n-m-1); Reverse(A,n-m,n-1); Reverse(A,0,n-1); } void display(int A[],int n,int m)//输出测试结果 {printf("移动前:"); for (int i=0;i #define N 4 void swap(int &x,int &y)//交换x和y {int tmp=x; x=y; y=tmp; } void trans(int B[])//转置算法 {int i,j; for (i=0;i #define m 3 #define n 4 int MinMax(int A[m][n],int &mini,int &maxj) {int i,j; int min[m],max[n]; for (i=0;imax[j]) max[j]=A[i][j]; } } for (i=0;ia[i][j],只能在同列后面行中找到x,即i++。这样比较次数不多于M+N次。对应的实验程序如下。 #include #define M 3 #define N 4 int Findx(int a[M][N],int x,int &i,int &j)//求解算法 {int flag=0; i=0; j=N-1; while (i=0) {if (a[i][j]!=x) {if (a[i][j]>x) j--;//修改列号 else i++;//修改行号 } else//a[i][j]==x {flag=1; break; } } return flag; } void display(int a[M][N],int x)//输出测试结果 {int i,j; if (Findx(a,x,i,j)) printf("a[%d][%d]=%d\n",i,j,x); else printf("查找%d失败\n",x); } int main() {int a[M][N]={{1,5,12,20},{2,7,15,25},{4,9,18,30}}; int x; x=2; printf("测试1: x=%2d ",x); display(a,x); x=15; printf("测试2: x=%2d ",x); display(a,x); x=9; printf("测试3: x=%2d ",x); display(a,x); 图5.7实验程序的执行结果 x=10; printf("测试4: x=%2d ",x); display(a,x); } 上述程序的执行结果如图5.7所示。 (6) 解: 对于稀疏矩阵三元组表示t,若其行号不等于列号,返回0; 否则通过扫描t.data数组累加行、列下标相同的元素值并返回1。对应的实验程序如下。 #define M 5 #define N 5 #include "TSMatrix.cpp"//包含稀疏矩阵三元组的基本运算函数 int Diagonal(TSMatrix t,ElemType &s)//求解算法 {int i; if (t.rows!=t.cols) return 0;//不是方阵 s=0; for (i=0;i