还是会想你:点击收听
1 基本知识点
1、数组可以看作是下标和值的偶对的集合(具有相同类型的数据元素)
注意:数组是同类型值的集合?**错误**
2、数组的存储方式:以行为主序(一行存储完成之后继续存储下一行)、以列为主序(一列存储完成之后继续存储下一列)
3、对矩阵压缩存储是为了减少存储空间
4、稀疏矩阵的三元组存储方法:
矩阵的非零元素个数和位置在操作过程中变化不大时较为有效
5、从逻辑结构上看,n维数组的每个元素均属于n个向量
二维数组:不但参与了行向量还参与了列向量
2 以行序为主序的数组计算元素的存储位置
1 因为第一维度i是从c1到d1,那么第一维度大小为:d1-c1+1
2 因为第二维度j是从c2到d2,那么第二维度大小为:d2-c2+1
3 数组的第一个元素为A[c1][c2],数组的首地址为Loc(c1,c2)
任何一个元素aij的内存地址 = 数组首地址+在aij前面存储的元素的个数(乘以)每个数组元素占用的存储单元L
1 aij之前的行数:i-c1
2 总的列数(每一行元素的个数):d2-c2+1
3 在aij这一行的第j列之前的元素个数:j-c2
4 注意:i在c1到d1之间、j在c2到d2之间
5 如果数组的下标是从1开始,那么c1 = c2 = 1
6 如果数组的下标是从0开始,那么c1 = c2 = 0
7 假设n为每一行的元素个数(总的列数)
可得:
下标从1开始存储:Loc(aij) = Loc(a11) + ((i-1)*n+j-1)*L
下标从0开始存储:Loc(aij) = Loc(a00) + (i*n+j)*L
3 矩阵的压缩存储
1、二维数组(矩阵),行和列相等时候为方阵
2、压缩存储:对于多个值相同的元素分配一个存储空间,对于零元素不分配空间
3.1 特殊矩阵
3.1.1 对称矩阵
满足:Aij = Aji(i和j处于0到(n-1)之间)
使用压缩存储的方式可以:
1 将n平方个元素压缩到n*(n+1)/2个空间中
2 以行序为主将该矩阵的下三角(包括对角线)中的元素存储到一个向量B[n*(n+1)/2]中
解释:n*(n+1)/2怎么得来的呢?
因为只需要存储下三角的元素,那么第一行需要存储1个、第二行需要存储2个…第n行需要存储n个,最后求和可得n*(n+1)/2个存储空间
将一个二维的矩阵压缩存储到一维的数组中,其中一维数组的大小为n*(n+1)/2
因为总共有n*(n+1)/2个空间,所以说下标为0到n*(n+1)/2 - 1
一维数组和二维矩阵的对应关系:
1、i和j从0开始:
如何推导出下三角的对应公式呢?
1 因为二维矩阵的下标是从0开始的
2 当获取aij的时候,比如说a21,那么a21正处于第三行第二列
3 所以说aij处于第i+1行
4 从第一行到第i行求和可得:1+2+...+i = i*(i+1)/2个元素
5 最后还要加上aij所在这一行的前面的元素个数,刚好等于j个元素
6 所以说下三角对应一维数组的下标为: k = i*(i+1)/2+j(i和j是从0开始)+0(不要忘了数组的起始下标)
2、i和j从1开始:
如何推导出下三角的对应公式呢?
1 因为二维矩阵的下标是从1开始的
2 当获取aij的时候,比如说a21,那么a21正处于第二行第一列
3 所以说aij处于第i行
4 从第一行到第i-1行求和可得:1+2+...+i-1 = i*(i-1)/2个元素
5 最后还要加上aij所在这一行的前面的元素个数,刚好等于j-1个元素
6 所以说下三角对应一维数组的下标为: k = i*(i-1)/2+j-1(i和j是从1开始)+1(不要忘了数组的起始下标)
3.1.2 三角矩阵
那么二维矩阵和一维数组之间的对应关系是:
例如:下三角矩阵
1、i和j从0开始:
1 其中下三角部分和对称矩阵一样(i和j从0开始)
2 需要多添加一个存储空间(因为上三角部分都为0或者一个常数)
3 本来元素总数是n*(n+1)/2个,对应的一维数组的下标为0到n*(n+1)/2 - 1
4 需要再添加一个空间就是在:n*(n+1)/2这个位置上存储那个常数或者0
2、i和j从1开始:
3.1.3 对角(带状)矩阵
1、下标从1开始:
将带状矩阵压缩存储到一维数组中
已知Aij如何计算在一维数组中的对应的下标值
注意:在3(i-1)的基础上,再加上起始下标1,就可得到对角线Aij在一维数组中的对应的下标值
那么用i和j来表示k:
k1 = 3(i-1) = 2(i-1)+i-1 i = j+1
k2 = 3(i-1)+1 = 2(i-1)+i-1+1 = 2(i-1)+i i = j
k3 = 3(i-1)+2 = 2(i-1)+i-1+2 = 2(i-1)+i+1 i = j-1
可得:**k = 2(i-1)+j**
如果用k来表示i和j呢?
floor代表向下取整
floor(x)返回的是**小于或等于x**的最大整数
1 i = floor(k/3) + 1
2 i和j具有对应关系
3 j = floor(k/3) + (k mod 3) (mod是求模运算)
三对角矩阵共有3n-2个元素
1 当n等于5的时候(5x5的三对角矩阵)
2 除了第一行和最后一行只有2个非零元素以外,其余各行都有3个非零元素
3 那么所需要的一维数组的大小为:2+2+3(n-2) = 3n-2
4 n = 5代入可得:为13个空间大小
5 压缩存储刚好需要13个空间大小
2、下标从0开始:
那么用i和j来表示k:
k1 = 3i-1 = 2i+i-1 = 2i+j i = j+1
k2 = 3i = 2i+i = 2i+j i = j
k3 = 3i+1 = 2i+i+1 = 2i+j i = j-1
可得:**k = 2i+j**
如果用k来表示i和j呢?
floor代表向下取整
floor(x)返回的是**小于或等于x**的最大整数
1 i = floor((k+1)/3)
2 i和j具有对应关系
3.2 稀疏矩阵
非零元素特别少并且分布无规律
存储结构:
1、顺序存储结构:三元组表(行号、列号、值)
2、链式存储结构:十字链表
稀疏因子:用矩阵中非零元素个数t除以矩阵的大小(mxn)<=0.05
3.2.1 基于三元组的矩阵转置
int m;//矩阵的行数
int n;//矩阵的列数
int len;//矩阵的非零元素的个数
//A为转置之前的矩阵
//B为转置以后的矩阵
B.m = A.n;
B.n = A.m;
B.len = A.len;
if(A.len)
{
q = 1;
//用q来作为B中元素的下标
//从1开始不断加加
for(j=1;j<=A.n;j++)
{
for(p=1;p<=A.len;p++)
{
if(A.data[p].col == j)
//A中保存的元素的列数和j相等
{
B.data[q].row = A.data[p].col;
B.data[q].col = A.data[p].row;
B.data[q].e = A.data[p].e;
q++;
}
}
}
return B;
}
3.2.2 矩阵的快速转置
两个数组的大小都和A.n大小相同
3.2.3 十字链表(链式存储形式)
非零元素在行和列的方向上都构成了单链表
4 典型题目解析
5 算法题目
1、矩阵中元素的查找
解释:
(行数相同的元素:从前到后递增)
(列数相同的元素:从上到下递增)
1 在第一行最后一个元素开始与待查找元素比较
2 如果比待查找元素小,移动到下一行的最后一个元素
3 在最后一行的最后一个元素的位置发现比待查找元素大
4 然后向前走
5 走到等于待查找元素
i = 0;
j = n-1;
flag = 0;
while(i<=(m-1)&&j>=0&&!flag)
{
if(A[i][j] == x)//等于
flag = 1;//找到
else if(A[i][j]>x)//大于
j--;//向左变小
else//小于
i++;//向下变大
}
if(flag)
//查找成功
else
//查找失败
6 易错题目
**易错:需要加上数组的起始下标1**