Bootstrap

数据结构(c语言) 多维数组和矩阵

一、数组

  • 可以是看作具有相同名称与相同数据类型的变量的集合,并且在内存中占据一块连续的内存空间。存取数组中的数据时,则需要使用下标来定位数据在数组中的位置。

数组包含下列五种属性

  1. 起始地址:表示数组名(或第一个元素)所在内存中的起始地址
  2. 维数:代表几维数组
  3. 下标的上下限:元素在数组中内存所存储的位置的最小值与最大值
  4. 数组元素个数:是下标上限与下标下限的差+1
  5. 数组类型:声明数组的类型决定数组元素在内存所占空间的大小。

1、一维数组

假设A为一维数组的名称,如果声明为A(1:n),表示A含有n个元素,其中1为下限,n为上限,则数组元素A(1)、A(2)等。a为A数组在内存中的起始位置,d为每一个数组元素所占用的空间,那么数组元素与内存地址有下列关系:

  • A(n) —— a+(n-1)*d
  • 在c语言中,一维数组的语法声明如下

数据类型 数组名【数组长度】

例如:int score [ 5 ]

//输出五名同学的成绩值并求和
#include<stdio.h>

int main(void)
{
	int score [5]={56,36,98,77,21};
	int sum=0;
	for(int i=1;i<=5;i++)
	{
		printf("第%d个同学成绩为:%d\n",i,score[i]);
		sum +=score[i];
	}
	printf("成绩总和为;%d",sum);
 } 
第1个同学成绩为:56
第2个同学成绩为:36
第3个同学成绩为:98
第4个同学成绩为:77
第5个同学成绩为:21
成绩总和为;288

2、二维数组

  • 二维数组的两种排列方式
  1. 以行为主:存放顺序为a11,a12,a1n,amm,假设a为数组在内存中的起始地址,d为单位空间,则数组元素aij与内存地址有下列关系:
  • Loc(aij)=a+n*(i-1)*d+(j-1)*d

     2、以列为主:存放顺序为a11,a21,am1,amm,同样的数组元素aij与内存地址有下列关系:

  • Loc(aij)=a+(i-1)*d+m*(j-1)*d
  • c语言中,二维数组的声明格式如下:

数据类型 二维数组名 【行大小】 【列大小】

例如:arr 【3】【5】

  • arr为一个3行5列的二维数组,也可以视为3x5的矩阵。使用的下标仍然是从0值开始计算

二维数组初始值的声明如下:

数据类型 数组名【n】【列大小】={{第0行初始值},{第一行初始值},...,{第n-1行初始值}}

例如:int arr 【2】【3】={{1,2,3},{2,3,4}}

/*使用二维数组计算:
1、每个业务代表的前半年业绩总额
2、1-6个月每个月这三个业务代表的总业绩*/
#include<stdio.h>
int main(void){
	
int arr[3][6]={{112,76,95,120,98,68},{90,120,88,112,108,120},{108,99,126,90,76,98}};
int sum1,sum2=0;
	for(int b=0;b<3;b++){
		sum1=0;
		for(int i=0;i<6;i++){
		 sum1+=arr[b][i]; 
		}
		printf("\n第%d号销售员的前半年销售总金额为:%d\n",b+1,sum1);
		
	}
		
		
	for(int i=0;i<6;i++){
		sum2=0;
		 for(int j=0;j<3;j++){
		 	sum2+=arr[j][i];
		 }
		 printf("\n所有销售员%d月的销售总金额为%d:\n",i+1,sum2);
	}

}

第1号销售员的前半年销售总金额为:569

第2号销售员的前半年销售总金额为:638

第3号销售员的前半年销售总金额为:597

所有销售员1月的销售总金额为310:

所有销售员2月的销售总金额为295:

所有销售员3月的销售总金额为309:

所有销售员4月的销售总金额为322:

所有销售员5月的销售总金额为282:

所有销售员6月的销售总金额为286:
//使用二维数组来求二阶行列式
#include<stdio.h>

int main(void)
{
	printf("|a1 b1|\n");
	printf("|a2 b2|\n");
	int a1,b1,a2,b2=0;
	int arr[2][2]={{0,0},{0,0}};
	printf("请输入a1:");
	scanf("%d",&a1);
	arr[0][0]=a1;
	printf("请输入b1:");
	scanf("%d",&b1);
	arr[0][1]=b1;
	printf("请输入a2:");
	scanf("%d",&a2);
	 arr[1][0]=a2;
	printf("请输入b2:");
	scanf("%d",&b2);
	 arr[1][1]=b2;
	printf("|%d %d|\n",a1,b1);
	printf("|%d %d|\n",a2,b2);
	int sum=arr[0][0]*arr[1][0]-arr[0][1]*arr[1][1];
	printf("sum=%d",sum);
	
 } 
|a1 b1|
|a2 b2|
请输入a1:6
请输入b1:3
请输入a2:2
请输入b2:4
|6 3|
|2 4|
sum=0

3、多维数组

  • 二维数组以上的数组都被称为多维数组
  • 如果数组A声明为(1:u1,1:u2,1:u3),表示A为1个含有u1*u2*u3元素的三维数组,可以看作是立方体。
  1. 以行为主:使用转换公式来计算A(i,j,k)排列在第几位。首先可以将数组A视为u1个u2*u3的二维数组,再将每个二维数组视为有u2个一维数组,每一个一维数组包含u3个元素,假定每个元素有d个单位空间,且a为数组的起始地址,则地址计算公式为:
  • Loc(A(i,j,k))=a+(i-1)u2u3d+(j-1)u3d+(k-1)d

     2.以列为主:可以将数组A视为u3个u2*u1的二维数组,再将每个二维数组视为有u2个一维数组,每一个一维数组含有u1个元素。假定每个元素有d单位空间,且a为起始地址。则aijk元素的地址计算公式为:

  • Loc(A(aijk))=a+(k-1)u2u1d+(j-1)u1d+(i-1)d
  • 如果把数组A声明为A(l1:u1,l2:u2,l3:u3)的标注表示法,且对任意的aijk,有u1>=i>=l1,u2>=j>=l2,u3>=k>=l3,则m=(u1-l1+1),n=(u2-l2+1),o=(u3-l3+1),这样就可以把数组A视为有m个二维数组,再将每个二维数组视为有n个一维数组,每一个一维数组含有o个元素,则aijk的地址计算公式为:
  1. 以行为主:Loc(A(aijk))=a+(i-l1)nod+(j-l2)od+(k-l3)d
  2. 以列为主:Loc(A(aijk))=a+(k-l3)mnd+(j-l2)md+(i-l1)d
  • 在c语言中,多维数组的定义方式如下

数据类型 数组名【元素个数】 【元素个数】 【元素个数】....,【元素个数】

例如:float No【2】【2】【2】//三维数组

int arr【2】【3】【4】【5】//四维数组

  • 三维数组的遍历
#include<stdio.h>

int main(void){
	int arr[2][2][2]={{{1,2},{3,3}},{{3,6},{5,8}}};
	int i,j,k;
	for(i=0;i<2;i++){
		for(j=0;j<2;j++){
			for(k=0;k<2;k++){
				printf("arr[%d][%d][%d]=%d\n",i,j,k,arr[i][j][k]);
			}
		}
	}
arr[0][0][0]=1
arr[0][0][1]=2
arr[0][1][0]=3
arr[0][1][1]=3
arr[1][0][0]=3
arr[1][0][1]=6
arr[1][1][0]=5
arr[1][1][1]=8
  • 三维数组求和并将特殊值进行替换
//求取三维数组所元素值的总和,并将所有为负数的值替换为0 
#include<stdio.h>

int main(void)
{
	int arr[4][3][3]={{{1,-2,3},{4,5,-6},{8,9,2}},{{7,-8,9},{10,11,12},{-1,3,2}},{{-13,14,15},{16,17,18},{3,6,7}}
	,{{19,20,21},{-22,23,24},{-6,9,12}}};
	int i,j,k;
	int sum=0;
	int cnt=0;
	for(i=0;i<4;i++){
		for(j=0;j<3;j++){
			for(k=0;k<3;k++){
			sum+=arr[i][j][k];
			if(arr[i][j][k]<0){
				arr[i][j][k]=0;
			}
		}
	}
}
		for(i=0;i<4;i++){
		for(j=0;j<3;j++){
			for(k=0;k<3;k++){
			printf("%d  ",arr[i][j][k]);
			cnt++;
			if(cnt%9==0)
			printf("\n\n");
		}
	}
	}printf("\n原数组的和为:%d",sum); 
} 
1  0  3  4  5  0  8  9  2

7  0  9  10  11  12  0  3  2

0  14  15  16  17  18  3  6  7

19  20  21  0  23  24  0  9  12


原数组的和为:252
  • 三维数组查找最小值
#include<stdio.h>

int main(void){
	
	int arr[2][3][3]={{{33,45,67},{23,71,56},{55,38,66}},{{21,9,15},{38,69,18},{90,101,89}}};
	
	int min=arr[0][0][0];
	int i,j,k;
	for(i=0;i<2;i++){
		for(j=0;j<3;j++){
			for(k=0;k<3;k++){
				if(min>arr[i][j][k]){
					min=arr[i][j][k];
				}
			}
		}
	}
	printf("最小值=%d\n",min);
}
最小值=9

4、结构数组

  • 结构数组允许用户自定义数据类型,又称为派生数据类型。

结构类型必须具有结构名称以及结构项目,而且必须使用关键字struct来创建,一个结构的基本声明方式如下:

struct 结构名称{

        数据类型 结构成员1;

        数据类型 结构成员2;

        ....

};

例如:struct student{

          char name[10];

          int score;

          int ID;

};

  • 在定义了结构之后,可以直接使用它来创建结构对象。
  • 结构对象的创建

1.直接创建

例如:struct s1,s2;

2.在定义结构的同时声明结构变量

例如:

struct student{

          char name[10];

          int score;

          int ID;

}s1,s2;

结构对象的使用

  • 在创建结构对象之后,可以使用英文句号.来存取结构成员,该句号被称为点运算符。

使用如下:结构变量.项目成员名称

例如:

strcpy(s1.name,"zhangsan');

s1.score=90;

s1.ID=10001;

结构数组是将结构数据类型与数组相结合的应用。

声明方式如下:

  • struct 结构类型名称 结构数组名【元素个数】

例如:

struct student {

        char name【10】;

         int math;

         int English;

};

struct student class1【5】;

  • 要存取数组的结构成员,在数组后方加上“【下标值】‘再加上成员名称即可,例如:

结构数组名【下标值】.成员名称

#include<stdio.h>

int main(void){
	struct stu{
		char name[10];
		int math;
		int Englishi;
	};//定义结构
	struct stu group[3]={{"zhangsan",87,63},{"lisi",92,87},{"wangmazi",63,98}};//定义并设置结构数组的初始值 
	int i;
    float math_sum,eng_sum=0;
	for(i=0;i<3;i++){
		math_sum+=group[i].math;
		eng_sum+=group[i].Englishi;
		printf("姓名:%s\t数学成绩:%d\t英语成绩:%d\t\n",group[i].name,group[i].math,group[i].Englishi);
	}
	for(i=0;i<50;i++){
		printf("=");
	}
}
姓名:zhangsan  数学成绩:87    英语成绩:63
姓名:lisi      数学成绩:92    英语成绩:87
姓名:wangmazi  数学成绩:63    英语成绩:98
==================================================

5、字符数组

c语言中,没有称为字符串的基本数据类型,如果在c程序中存储字符串,就必须使用字符数组来表示。

  • 例如:‘a’是一个字符常数,而“a”是一个字符串常数。差别在于字符串的末尾处会多安排一个字节的空间来存放”\0“字符,作为字符串结束的符号。

字串的声明如下:

  • 方式一:char 字符串常量【字符串长度】=“ 初始字符串”;
  • 方式二:char 字符串常量【字符串长度】={‘字符1’,‘字符2’,...‘字符n’,‘\0’};

例如:

  • char str1[6]="Hello";
  • char str2[6]={'H','e','l','l','o','\0'};
  • char str3[ ]="Hello";
  • 注意:由于字符串不是C的基本数据类型,无法利用数组名来直接给另一个字符串数组赋值,如果需要进行字符串的赋值,必修从字符串数组中一个一个取出元素的内容进行复制。

字符串长度的计算

int main(void){
	int n;
	char str[100];
	printf("请输入字符串:");
	scanf("%s",&str);
	while(str[n]!='\0'){
		n++;
	}
	printf("\n输入的字符串为%s\n",str);
	printf("此字符串有%d个字符",n);
} 
请输入字符串:aksdkaksda
输入的字符串为aksdkaksda
此字符串有10个字符

字符串大小写的转换

int main(void){
	char s[100];
	printf("请输入一个字符串:");
	scanf("%s",&s);
	int n=0;
	while(s[n]!='\0'){
		if(s[n]>='a'&&s[n]<='z'){
			s[n]-=32;
		}
		n++;
	}
	printf("\n大小写转换后的字符串为%s\n",s);
}
请输入一个字符串:lasdkasd

大小写转换后的字符串为LASDKASD

字符串的反转

int main(void){
	char s[100];
	printf("请输入一个字符串:");
	scanf("%s",&s);
	int n=0;
	while(s[n]!='\0'){
		n++;
	}
	printf("字符串反转后为:"); 
	for(int len=n;len>=0;len--){
		printf("%c",s[len]);
	}
	
}
请输入一个字符串:lobeadsada
字符串反转后为: adasdaebol

6、字符串数组

  • 字符串数组可以理解为二维的字符数组

字符串数组的声明方式如下

  • char 字符串数组名【字符串数】 【字符数】;
  • 上述字符串数表示字符串的个数,而字符数表示的是每个字符串最多可容纳多少字符。

字符串数组也可以在声明时就设置初始值

char 字符串数组名【字符串数】【字符数】={“字符串常数1”,“字符串常数2”,“字符串常数3”,...};

  • 例如:char Name[5] [10] ={ "John","Mary","Wilson","Candy","Allen"};

字符串数组的遍历

int main(void){
	char name[5][20]={"zhangsan","lisi","wangmaizi", 
					  "wangwu","huangsan"};
	for(int i=0;i<5;i++){
		printf("name[%d]=%s\n",i,name[i]);
	}
}
name[0]=zhangsan
name[1]=lisi
name[2]=wangmaizi
name[3]=wangwu
name[4]=huangsan

7、指针数组

  • 每个指针数组中的元素都是一个指针变量,而元素值则为只想其他变量的地址值

一维指针数组的声明格式:

数据类型 *数组名【元素名称】;

例如:

  • int *p【3】; float *ptr【4】;

一维指针数组应用于字符串存储中可避免字符串数组中对于内存空间的浪费

例如:char *name【4】={“zhangsan”,"lisi" ,“wangmazi”,“wangwu”};

  • 该声明中,每个数组元素name【i】都是用来存储内存的地址,他们分别存储了指向字符串的内存地址。

二、矩阵

  • 对于m x n矩阵的形式,可以用A(m,n)的二维数组来描述。

1、矩阵的运算

转置矩阵:把原矩阵的行坐标与列坐标相互调换,假设At为A的转置矩阵,则有At【j,i】=A【i,j】

  • 算法如下
for(i=0;i<m;i++){
    for(j=0;j<n;j++){
        arrB[i][j]=arrA[i][j];
    }
}
  • 4*4矩阵的转置
int main(void){
	int arrA[4][4];
	int arrB[4][4];
	int i,j;
	int cnt=0;
	printf("【请输入矩阵的内容】\n"); 
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){
			scanf("%d",&arrA[i][j]);
			
		}
	}
	printf("\n【转置的矩阵内容为】\n");
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){
			arrB[i][j]=arrA[j][i];
			printf("%d ",arrB[i][j]);
			cnt++;
			if(cnt%4==0){
				printf("\n");
			}
		}
	} 
}
【请输入矩阵的内容】
1 2 3 4
3 2 1 4
6 6 6 6
5 8 5 9

【转置的矩阵内容为】
1 3 6 5
2 2 6 8
3 1 6 5
4 4 6 9

矩阵的加法运算

  • 相加的两个矩阵行数与列数必须相等,相加后矩阵的行数与列数也必须相同。
2个m*n矩阵相加的算法如下:
for(i=0;i<3;i++)
    for(j=0;j<3;j++)
    C[i][j]= A[i][j]+B[i][j];//矩阵C=矩阵A+矩阵B
#include<stdio.h>

int main(void){
	int a[3][3]={{2,3,4},{4,5,6},{5,6,9}};
	int b[3][3]={{3,4,5},{6,7,8},{2,6,8}};
	int c[3][3];
	int i,j;
	int cnt=0;
	printf("矩阵相加后结果为:\n");
	for(i=0;i<3;i++){
		for(j=0;j<3;j++){
			c[i][j]=a[i][j]+b[i][j];
			cnt++;
			printf(" %d ",c[i][j]);
			if(cnt%3==0){
				printf("\n");
			}
			
		}
	}
} 
矩阵相加后结果为:
 5  7  9
 10  12  14
 7  12  17

矩阵的乘法运算

  • 矩阵A*B,首先必须符合A为一个m*n矩阵,B为一个n*p矩阵,A*B之后的结果为一个m*p的矩阵C。
m*n矩阵与n*怕矩阵相乘的算法如下
for(i=0;i<3;i++)
    for(j=0;j<3;j++)
    {
    c[i][j]=0;
    for(k=0;k<2;k++)
    c[i][j]=c[i][j]+A[i][k]*B[k][j];
    }//矩阵C=矩阵A*矩阵B
#include<stdio.h>

int main(void){
	int i,j,k,m,n,p,q;

	printf("请输入矩阵a的维数(m,n):\n");
	scanf("%d %d",&m,&n);
	int a[m][n]={0};
	printf("【请输入矩阵a的元素】\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			printf("a%d%d=",i,j);
			scanf("%d",&a[i][j]);
		}
	}
	getchar();
	printf("请输入矩阵b的维数(n,p):\n");
	scanf("%d %d",&p,&q	);
	int b[n][p]={0};
	printf("【请输入矩阵b的元素】\n");
	for(i=0;i<p;i++){
		for(j=0;j<q;j++){
			printf("b%d%d=",i,j);
			scanf("%d",&b[i][j]);
		}
	}
	getchar(); 
	printf("a*b的结果为:\n");
	int c[m][p]={0};
	int cnt=0;
	printf("%d %d %d\n",m,n,p);
	for(i=0;i<m;i++){
		for(j=0;j<p;j++){
			
			c[i][j]=0;
			for(k=0;k<n;k++){
				c[i][j]=c[i][j]+a[i][k]*b[k][j];
				}
				
			}
		}
	
	for(i=0;i<m;i++){
		for(j=0;j<m;j++){
			printf(" %d ",c[i][j]);
			cnt++;
			if(cnt%2==0){
				printf("\n");
			}
		}
	} 
}
请输入矩阵a的维数(m,n):
2 3
【请输入矩阵a的元素】
a00=1
a01=2
a02=3
a10=4
a11=5
a12=6
请输入矩阵b的维数(n,p):
3 2
【请输入矩阵b的元素】
b00=6
b01=5
b10=4
b11=3
b20=2
b21=1
a*b的结果为:
2 3 3
 20  14
 56  41

2、稀疏矩阵

  • 如果一个矩阵中的大部分元素为零的话,就被称为稀疏矩阵。
  • 稀疏矩阵实际存储的数据项很少,若果在计算机中使用传统的二维数组来存储十分浪费内存空间。提高利用率的方法时利用三项式的数据结构。
  • 三项式:将每一个非零项以(i,j,item-value)来表示。i表示所在行数,j表示所在列数,item-value表示数值。
  • 如果一个稀疏矩阵由n个非零项,可以利用A(0:n,1:3)的二维数组来存储这些非零项,把这样存储的矩阵叫作压缩矩阵。其中A(0,1)存储这个矩阵的行数,A(0,2)存储这个稀疏矩阵的列数,而A(0:3)是此稀疏矩阵除非零项的总数。
  • 存取压缩数组的算法:
Compress[0][0]=6;//此稀疏矩阵的行数
Comperss[0][1]=6;//此系数矩阵的列数
Compress[0][2]=NONZERO;//此稀疏矩阵除非零项的总数
for(i=0;i<6;i++)
    for(j=0;j<6;j++)
    if(Spare[i][j]!=){
        Compress[temp][0]=i;
        Compress[temp][1]=j;
        Compress[temp][2]=Sparse[i][j];
        temp++;
        }
  • 6*6稀疏矩阵的压缩
#include<stdio.h>

int main(void){
	int a[6][6]={};
	int i,j,k,cnt=0;
	int n=0;
	int temp=0; 
	printf("【请为矩阵赋值】\n");
	for(i=0;i<6;i++){
		for(j=0;j<6;j++){
			printf("a%d%d=",i,j);
			scanf("%d",&a[i][j]);
			if(a[i][j]!=0){
				n++;
			}
		}
	}
	
	printf("\n【稀疏矩阵的各个元素】\n"); 
	 for(i=0;i<6;i++){
		for(j=0;j<6;j++){
			printf("[%d]\t",a[i][j]);
			if(a[i][j]!=0){
			}
			cnt++;
			if(cnt%6==0){
				printf("\n"); 
			}
			
		}
	}
	int c[100][3]={};

	printf("\n【稀疏矩阵压缩后内容】\n");
	c[0][0]=6;
	c[0][1]=6;
	c[0][2]=n;
	for(int m=0;m<3;m++){
		printf("[%d]\t",c[0][m]);
	}
	printf("\n");
	int cnts=1;
	for(i=0;i<6;i++){
		for(j=0;j<6;j++){
			if(a[i][j]!=0){
				
			c[temp][0]=i;
			c[temp][1]=j;
			c[temp][2]=a[i][j];
			 temp++;
		 }	
	  }
	}
  for(i=0;i<temp;i++){
  	for(j=0;j<3;j++){
  		printf("[%d]\t",c[i][j]);
  		cnt++;
  		if(cnt%3==0)
  		printf("\n");
	  }
  }
}
【请为矩阵赋值】
a00=0
a01=0
a02=0
a03=0
a04=0
a05=0
a10=0
a11=0
a12=0
a13=0
a14=0
a15=0
a20=0
a21=0
a22=0
a23=01
a24=2
a25=34
a30=5
a31=6
a32=3
a33=2
a34=1
a35=0
a40=3
a41=2
a42=1
a43=0
a44=3
a45=2
a50=1
a51=0
a52=5
a53=9
a54=9
a55=7

【稀疏矩阵的各个元素】
[0]     [0]     [0]     [0]     [0]     [0]
[0]     [0]     [0]     [0]     [0]     [0]
[0]     [0]     [0]     [1]     [2]     [34]
[5]     [6]     [3]     [2]     [1]     [0]
[3]     [2]     [1]     [0]     [3]     [2]
[1]     [0]     [5]     [9]     [9]     [7]

【稀疏矩阵压缩后内容】
[6]     [6]     [18]
[2]     [3]     [1]
[2]     [4]     [2]
[2]     [5]     [34]
[3]     [0]     [5]
[3]     [1]     [6]
[3]     [2]     [3]
[3]     [3]     [2]
[3]     [4]     [1]
[4]     [0]     [3]
[4]     [1]     [2]
[4]     [2]     [1]
[4]     [4]     [3]
[4]     [5]     [2]
[5]     [0]     [1]
[5]     [2]     [5]
[5]     [3]     [9]
[5]     [4]     [9]
[5]     [5]     [7]

--------------------------------

上三角形矩阵

  • 上三角形矩阵就是一种对角线以下元素都为0的n*n矩阵。上三角形矩阵又可以分为右上三角形与左上三角形矩阵。由于上三角形矩阵仍有许多元素为0,为节省内存空间。我们可以把三角形矩阵的二维模式,存储在一维数组中。

1、右上三角形矩阵

  • 对于n*n的矩阵A,假如i>j,那么A(i,j)=0
  • 由于此二维矩阵的非零项可以按顺序映射到一维矩阵且需要一个一维数组B(1:n*(n+1)/2)来存储。映射方式可以以行为主或者以列为主
  • 以行为主时:aij会存放在B(k)中。k=n*(i-1)-i*(i-1)/2   + j
  • 以列为主时:aij回存放在B(k)中。k=j*(j-1)/2    + i
  • 右上三角形压缩为一维数组的代码实现
#include<stdio.h>

int main(void){
	int m,n,i,j=0; 
	printf("请输入矩阵a的维数(m,n):\n");
	scanf("%d %d",&m,&n);
	int a[m][n]={0};
	int cnt1=0;
	printf("【请输入矩阵a的元素】\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			if(i<=j){
			printf("a%d%d=",i,j);
			scanf("%d",&a[i][j]);
			cnt1++;
			}else{
				a[i][j]=0;
			} 
		}
	}
	printf("\n上三角形矩阵:\n");
	int b[cnt1]={0};
	int cnt2=0;
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			printf("%d\t",a[i][j]);
			cnt2++;
			if(cnt2%n==0){
				printf("\n");
			}
		}
	}printf("\n以一维数组的方式表示:\n");
		int k=0;
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			if(a[i][j]!=0){
				b[k]=a[i][j];
				printf("%d\t",b[k]);
				k++;
			}
		}
	}
  } 
请输入矩阵a的维数(m,n):
3 3
【请输入矩阵a的元素】
a00=1
a01=2
a02=3
a11=4
a12=5
a22=6

上三角形矩阵:
1       2       3
0       4       5
0       0       6

以一维数组的方式表示:
1       2       3       4       5       6

2、左上三角形矩阵

  • n*n的矩阵A,假如i>n-j+1时,A(i,j)=0.
  • 以行为主:k=n*(i-1)-((i-2)*(i-1))/2+j
  • 以列为主:k=n*(j-1)-((j-2)*(j-1))/2+i

下三角形矩阵

  • 对角线以上元素都为0的n*n矩阵。

1、左下三角形矩阵

  • 即对n*n的矩阵A,假如i>n-j+1时,A(i,j)=0
  • 以行为主:将aij存储在B(k)中,k=n*(i-1)-((i-2)*(i-1))/2   + j
  • 以列为主:将aij存储在B(k)中,k=n*(j-1)-((j-2)*(j-1))/2   + i
  • 左下三角形矩阵压缩为一维数组的代码实现
#include<stdio.h> 

int main(void){
	int m,n,i,j=0; 
	printf("请输入矩阵a的维数(m,n):\n");
	scanf("%d %d",&m,&n);
	int a[m][n]={0};
	int cnt1=0;
	printf("【请输入矩阵a的元素】\n");
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			if(i>=j){
			printf("a%d%d=",i,j);
			scanf("%d",&a[i][j]);
			cnt1++;
			}else{
				a[i][j]=0;
			} 
		}
	}
	printf("\n下三角形矩阵:\n");
	int b[cnt1]={0};
	int cnt2=0;
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			printf("%d\t",a[i][j]);
			cnt2++;
			if(cnt2%n==0){
				printf("\n");
			}
		}
	}printf("\n以一维数组的方式表示:\n");
		int k=0;
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			if(a[i][j]!=0){
				b[k]=a[i][j];
				printf("%d\t",b[k]);
				k++;
			}
		}
	}
  } 
请输入矩阵a的维数(m,n):
3 3
【请输入矩阵a的元素】
a00=1
a10=2
a11=3
a20=4
a21=5
a22=6

下三角形矩阵:
1       0       0
2       3       0
4       5       6

以一维数组的方式表示:
1       2       3       4       5       6
--------------------------------

2、右下三角形矩阵

  • 对于n*n的矩阵,假如i<n-j+1,那么A(i,j)=0.
  • 以行为主:aij存储在B(k)中,k=i*(i+1)/2   +j-n
  • 以列为主:aij存储在B(k)中,k=j*(j+1)/2   +i-n

带装矩阵

  • 在上三角形矩阵中,右上方的元素均为零。在下三角形矩阵中,左下方的元素也为零。即除了第一行与第n行有两个元素外,其余每行都具有三个元素。
  • 带状矩阵也是稀疏矩阵的一种。在存储上也只将非零项存储到一维数组中,映射关系同样为以行为主或者以列为主。
  • 例如,对以行为主的存储方式。aij存储到B(k)中,k=2i+j-2。
;