若矩阵中的非零元素远远小于矩阵元素的个数,且分布没有规律,则称这个矩阵为稀疏矩阵。
压缩存储是指对多个值相同的元素只分配一个存储空间,对零元素不分配空间。
稀疏矩阵的压缩存储有两种方法:三元组的顺序存储(三元组表)和链式存储(十字链表)。
现在主要讲三元组表,由于两个阶数不同的矩阵可能具有相同的非零元素,为了区别,在存储三元组时,同时还应存储该矩阵的行数、列数。通常为了运算的方便,也存放非零元素的个数。这种以顺序存储
压缩存储是指对多个值相同的元素只分配一个存储空间,对零元素不分配空间。
稀疏矩阵的压缩存储有两种方法:三元组的顺序存储(三元组表)和链式存储(十字链表)。
现在主要讲三元组表,由于两个阶数不同的矩阵可能具有相同的非零元素,为了区别,在存储三元组时,同时还应存储该矩阵的行数、列数。通常为了运算的方便,也存放非零元素的个数。这种以顺序存储
结构来表示三元组的线性表,称之为三元组表。稀疏矩阵的存储的三元组表的存储结构可定义如下:
#define MAXSIZE 1000 //用户自定义三元组最大个数
typedef int ElemType;
typedef struct { //三元组
int row,col; //非零元素的行数和列数
ElemType e; //非零元素的值
}Triple;
typedef struct {
Triple data[MAXSIZE]; //三元组表
int m,n, len; //矩阵的行数、列数和非零个数
}TSMatrix;
(1)三元组表的矩阵转置运算-“直接取,顺序存”
//转置
TSMatrix TransTSMatrixSlow(TSMatrix a,TSMatrix b) {
int q;
b.m = a.n;
b.n = a.m;
b.len = a.len;
if (b.len) {
q = 0; //B中的非零个数
for (int j = 0; j < a.n;j++) { //按列转置
for (int h = 0; h < a.len; h++) {
if (j==a.data[h].col) { //本列中一个非零元素
b.data[q].row = a.data[h].col;
b.data[q].col = a.data[h].row;
b.data[q].e = a.data[h].e;
q++;
}
}
}
}
else {
cout << "矩阵为空,无需转置!" << endl;
}
return b;
}
但是每处理一列就要查遍三元组表,工作量比较大
(2)三元组表的矩阵快速转置运算-“顺序取,直接存”
//快速转置
TSMatrix TransTSMatrixFast(TSMatrix a, TSMatrix b) {
int number[MAXSIZE],position[MAXSIZE];
b.m = a.n;
b.n = a.m;
b.len = a.len;
for (int j = 0; j < a.n;j++) {
number[j] = 0; //将矩阵a每一列非零元素的个数初始化为零
}
for (int t = 0; t < a.len; t++) {
number[a.data[t].col]++; //求每一列非零元素的个数
}
position[0] = 0;
for (int j = 1; j < a.n; j++) { //a.data[]的第j列第一个非零元素在b.data中的序号
position[j] = position[j - 1] + number[j - 1];
}
int j,q;
for (int p = 0; p < a.len; p++) { //求转置矩阵b的三元组表
j = a.data[p].col;
q = position[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;
position[j]++;
}
return b;
}
核心:若用number数组记录矩阵A中每列的非零元素个数,用position数组记录A中每列第一个非零元素在三元组表中的位置,则若第j-1列的第一个非零元素在position[j-1]的位置上,第j列的第一个非零元素必在第position[j-1]+number[j-1]位置上。
完整代码:
#include<iostream>
using namespace std;
#define MAXSIZE 1000 //用户自定义三元组最大个数
typedef int ElemType;
typedef struct { //三元组
int row,col; //非零元素的行数和列数
ElemType e; //非零元素的值
}Triple;
typedef struct {
Triple data[MAXSIZE]; //三元组表
int m,n, len; //矩阵的行数、列数和非零个数
}TSMatrix;
//输出矩阵
void print(TSMatrix a){
int k;
for (int i = 0; i < a.m;i++) {
for (int j = 0; j < a.n;j++) {
k = 0;
for(int h=0;h<a.len;h++){
if (i == a.data[h].row && j==a.data[h].col) {
cout <<" "<< a.data[h].e;
k = 1;
}
}
if (k == 0) {
cout << " " << k;
}
}
cout << endl;
}
}
//转置
TSMatrix TransTSMatrixSlow(TSMatrix a,TSMatrix b) {
int q;
b.m = a.n;
b.n = a.m;
b.len = a.len;
if (b.len) {
q = 0; //B中的非零个数
for (int j = 0; j < a.n;j++) { //按列转置
for (int h = 0; h < a.len; h++) {
if (j==a.data[h].col) { //本列中一个非零元素
b.data[q].row = a.data[h].col;
b.data[q].col = a.data[h].row;
b.data[q].e = a.data[h].e;
q++;
}
}
}
}
else {
cout << "矩阵为空,无需转置!" << endl;
}
return b;
}
//快速转置
TSMatrix TransTSMatrixFast(TSMatrix a, TSMatrix b) {
int number[MAXSIZE],position[MAXSIZE];
b.m = a.n;
b.n = a.m;
b.len = a.len;
for (int j = 0; j < a.n;j++) {
number[j] = 0; //将矩阵a每一列非零元素的个数初始化为零
}
for (int t = 0; t < a.len; t++) {
number[a.data[t].col]++; //求每一列非零元素的个数
}
position[0] = 0;
for (int j = 1; j < a.n; j++) { //a.data[]的第j列第一个非零元素在b.data中的序号
position[j] = position[j - 1] + number[j - 1];
}
int j,q;
for (int p = 0; p < a.len; p++) { //求转置矩阵b的三元组表
j = a.data[p].col;
q = position[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;
position[j]++;
}
return b;
}
void main() {
TSMatrix A, B;
A.m = 5;
A.n = 6;
A.len = 7;
A.data[0].row = 0; A.data[0].col = 1; A.data[0].e = 6;
A.data[1].row = 0; A.data[1].col = 5; A.data[1].e = -2;
A.data[2].row = 2; A.data[2].col = 3; A.data[2].e = -8;
A.data[3].row = 3; A.data[3].col = 1; A.data[3].e = 3;
A.data[4].row = 3; A.data[4].col = 5; A.data[4].e = 7;
A.data[5].row = 4; A.data[5].col = 0; A.data[5].e = -12;
A.data[6].row = 4; A.data[6].col = 2; A.data[6].e = 9;
cout << "矩阵A为:" << endl;
print(A);
cout << "求系数矩阵A的转置矩阵B?" << endl;
B = TransTSMatrixSlow(A,B);
cout << "转置矩阵B为:" << endl;
print(B);
cout << endl;
B = TransTSMatrixFast(A,B);
print(B);
system("pause");
}