实验目的:熟练掌握对称矩阵压缩存储的方法,并能运用此方法进行实际应用。
实验内容:对于n×n阶的对称矩阵,其元素分布的特点是a[i][j]=a[j][i],在存储时,只需压缩存储对称矩阵的上三角或下三角元素,但两个对称矩阵相乘的结果不一定是对称矩阵。
实验要求:
(1)创建名为kcsj14.cpp的文件,在其中编写两个对称矩阵相乘的程序。
(2)分别输入对称矩阵的元素。
(3)将这两个矩阵相乘,所得结果存入一个n×n阶的矩阵中,输出存放结果的矩阵。
(4)若输出为上三角或下三角矩阵,则需对其进行压缩存储。
import java.util.Scanner;
class Matrix {
// 定义矩阵大小
int N;
// 这里用一维数组存储对称矩阵压缩后的下上角
int[] m;
// 带参数的构造函数
public Matrix(int N, int[] M) {
this.N = N;
this.m = M;
}
// 做矩阵乘法
int[][] mul(Matrix M) {
// 声明N * N的二维数组存放计算结果
int[][] ans = new int[N][N];
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
ans[i][j] = 0;
for(int k = 0; k < N; k++) {
// 矩阵乘法ans[i][j] = ans[i][j] + M1[i][k] * M2[k][j];
// 这里将上式中的M1[i][k]和M2[k][j]分开计算
int temp = 1;
if(i >= k) temp = temp * m[i*(i+1)/2 + k];
else temp = temp * m[k*(k+1)/2 + i];
if(k >= j) temp = temp * M.m[k*(k+1)/2 + j];
else temp = temp * M.m[j*(j+1)/2 + k];
ans[i][j] = ans[i][j] + temp;
}
}
}
return ans;
}
// 判断矩阵是上三角、下三角、对称矩阵或者常规矩阵
static int judge(int[][] M, int N) {
// flag[0]为真表示是上三角,flag[1]表示下三角,flag[2]表示对称矩阵
boolean[] flag = new boolean[3];
// 初始化为全真
flag[0] = flag[1] = flag[2] = true;
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
// 当下三角部分不全为0时,该矩阵不是上三角矩阵
if(i > j && M[i][j] != 0) flag[0] = false;
// 当上三角部分不全为0时,该矩阵不是下三角矩阵
if(i < j && M[i][j] != 0) flag[1] = false;
// 当M[i][j] != M[j][i]时,该矩阵不是对称矩阵
if(M[i][j] != M[j][i]) flag[2] = false;
}
}
// 返回判断结果1表示上三角、2表示下三角、3表示对称矩阵、4表示常规矩阵
if(flag[0]) return 1;
else if(flag[1]) return 2;
else if(flag[2]) return 3;
else return 4;
}
// 按类型输出矩阵
static void printMatrix(int[][] M, int status, int N) {
switch(status) {
case 1:{ // 压缩输出上三角矩阵
System.out.println("(此矩阵为上三角矩阵,压缩后如下)");
int[] out = new int[N*(N+1)/2];
for(int i = 0; i < N; i++) {
for(int j = i; j < N; j++) {
// 上三角与原矩阵的对应关系为M[i][j] = m[i*(2*N-i+1)/2 + j - i];
out[i*(2*N-i+1)/2 + j - i] = M[i][j];
}
}
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
if(i <= j) System.out.printf("%10d", out[i*(2*N-i+1)/2 + j - i]);
else System.out.printf(" ");
}
System.out.println();
}
break;
}
case 2:{ // 压缩输出下三角矩阵
System.out.println("(此矩阵为下三角矩阵,压缩后如下)");
int[] out = new int[N*(N+1)/2];
for(int i = 0; i < N; i++) {
for(int j = 0; j <= i; j++) {
// 下三角矩阵与原矩阵的对应关系为M[i][j] = m[i*(i+1)/2 + j];,下同。
out[i*(i+1)/2 + j] = M[i][j];
}
}
for(int i = 0; i < N; i++) {
for(int j = 0; j <= i; j++) {
System.out.printf("%10d", out[i*(i+1)/2 + j]);
}
System.out.println();
}
break;
}
case 3:{ // 压缩输出对称矩阵
System.out.println("(该矩阵为对称矩阵,压缩后的下三角部分如下)");
int[] out = new int[N*(N+1)/2];
for(int i = 0; i < N; i++) {
for(int j = 0; j <= i; j++) {
// 将矩阵压缩,同上
out[i*(i+1)/2 + j] = M[i][j];
}
}
for(int i = 0; i < N; i++) {
for(int j = 0; j <= i; j++) {
System.out.printf("%10d", out[i*(i+1)/2 + j]);
}
System.out.println();
}
break;
}
case 4:{ // 输出常规矩阵
System.out.println("(该矩阵为常规矩阵)");
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
System.out.printf("%10d", M[i][j]);
}
System.out.println();
}
break;
}
default:{
System.out.println("错误: 传入的状态码有误!!");
}
}
}
}
public class kcsj14 {
public static void main (String args[]) {
Scanner sc = new Scanner(System.in);
int N;
System.out.print("需要计算的矩阵阶数: ");
N = sc.nextInt();
int[] M1 = new int[N*(N+1)/2];
int[] M2 = new int[N*(N+1)/2];
System.out.println("输入A矩阵的下三角部分:");
for(int i = 0; i < N; i++) {
for(int j = 0; j <= i; j++) {
// 下三角矩阵的对应关系为M[i][j] = m[i*(i+1)/2 + j];
M1[i*(i+1)/2 + j] = sc.nextInt();
}
}
// 声明A矩阵
Matrix A = new Matrix(N, M1);
System.out.println("输入B矩阵的下三角部分:");
for(int i = 0; i < N; i++) {
for(int j = 0; j <= i; j++) {
// 下三角矩阵的对应关系为M[i][j] = m[i*(i+1)/2 + j];
M2[i*(i+1)/2 + j] = sc.nextInt();
}
}
// 声明B矩阵
Matrix B = new Matrix(N, M2);
// 存放结果
int[][] ans = A.mul(B);
System.out.print("A * B的计算结果为: ");
Matrix.printMatrix(ans, Matrix.judge(ans, A.N), A.N);
}
}