所谓压缩存储,是指对多个值相同的元素只分配一个空间,对零元素不分配空间。
一、特殊矩阵
特殊矩阵是指值相同的元素分布具有一定规律的矩阵,如对角矩阵、三角矩阵,对称矩阵等,对于此类矩阵,找到一个关系将其元素存储到一维数组中,通过这个关系可以对矩阵中的元素进行随机存取。
二、稀疏矩阵
稀疏矩阵中也含有较多的零元素,但是非零元素的分布没有任何规律,因此在存储非零元素的同时,还必须存储适当的辅助信息,才能迅速确定一个非零元素是矩阵中的哪一个元素。稀疏矩阵的表示有很多种方法,下面仅分析用三元组表示稀疏矩阵存储的方法。
矩阵中非零元素的行号、列号及元素值组成了三元组,三元组按行优先(或列优先)的顺序排列得到一个其结点均是三元组的线性表,此外,要唯一的确定一个稀疏矩阵,还必须确定矩阵的行数和列数,为了方便,还要将非零元素个数存储起来,于是得到稀疏矩阵的一种类型如下:
#define MAX 12
typedef int datatype;
typedef struct
{
int i, j; //行号、列号
datatype v; //元素值
} node;
typedef struct
{
int m, n, t; //行数,列数,非零元素个数
node data[MAX]; //三元组表
}spmatrix;
三、算法分析举例
下面以矩阵的转置简单说明一下如何用稀疏矩阵进行矩阵运算:
将矩阵A转置为B,即B[i][j] = A[j][i],这样看来,其实只需将三元组中的i与j 数值交换即可,但是这样做,转置后的矩阵就不会按照行优先或列优先的顺序在线性表中排列了。由于A的列是B的行,因此按A的列顺序进行转置,得到的转置矩阵B必然是按行排列的,具体算法描述如下:
spmatrix *TransMat(spmatrix *a) //稀疏矩阵的转置
{
int p, q, bno = 0;
spmatrix *b;
b = (spmatrix *)malloc(sizeof(spmatrix)); //为矩阵b分配内存空间
b->m = a->n;
b->n = a->m;
b->t = 0;
if (a->t == 0) //若b中元素全为零,则将b返回
return b;
for (p = 0; p < a->n; p++)
for (q = 0; q < a->t; q++)
if (a->data[q].j == p)
{
b->data[bno].i = a->data[q].j;
b->data[bno].j = a->data[q].i;
b->data[bno].v = a->data[q].v;
bno++;
}
b->t = bno;
return b;
}
上述算法有双重循环,若A有n列t个非零元素,则算法复杂度为O(n x t),若用二维矩阵存储,A有m行n列,则算法复杂度为O(n x m),一般t远大于m,因此在此例中,稀疏矩阵转置算法执行时间更长一些。
四、完整程序举例
下面写一个完成的C程序来测试稀疏矩阵三元组结构及转置算法,程序输入为一个3行4列的整数矩阵,输出转置矩阵。
/* 稀疏矩阵的类型说明及转置算法 */
#include<stdio.h>
#include<stdlib.h>
#define MAX 12
typedef int datatype;
typedef struct
{
int i, j; //行号、列号
datatype v; //元素值
} node;
typedef struct
{
int m, n, t; //行数,列数,非零元素个数
node data[MAX]; //三元组表
}spmatrix;
spmatrix *Create(); //创建一个3行4列的稀疏矩阵
spmatrix *TransMat(spmatrix *a); //稀疏矩阵的转置
void Output(spmatrix *a); //在屏幕上以行列的形式输出矩阵
int main()
{
spmatrix *a = Create();
spmatrix *b = TransMat(a);
printf("原矩阵:\n");
Output(a);
printf("转置矩阵:\n");
Output(b);
return 0;
}
spmatrix *Create() //创建一个3行4列的稀疏矩阵
{
int m = 3, n = 4, k = 0, t = 0;
datatype element;
spmatrix *matrix;
matrix = (spmatrix *)malloc(sizeof(spmatrix)); //创建一个稀疏矩阵a
matrix->m = m;
matrix->n = n;
printf("输入12个整数:\n");
while (k < m*n)
{
scanf_s("%d", &element);
if (element != 0)
{
matrix->data[t].i = k / n;
matrix->data[t].j = k % n;
matrix->data[t].v = element;
t++;
}
k++;
}
matrix->t = t;
return matrix;
}
spmatrix *TransMat(spmatrix *a) //稀疏矩阵的转置
{
int p, q, bno = 0;
spmatrix *b;
b = (spmatrix *)malloc(sizeof(spmatrix)); //为矩阵b分配内存空间
b->m = a->n;
b->n = a->m;
b->t = 0;
if (a->t == 0) //若b中元素全为零,则将b返回
return b;
for (p = 0; p < a->n; p++)
for (q = 0; q < a->t; q++)
if (a->data[q].j == p)
{
b->data[bno].i = a->data[q].j;
b->data[bno].j = a->data[q].i;
b->data[bno].v = a->data[q].v;
bno++;
}
b->t = bno;
return b;
}
void Output(spmatrix *a)
//输入:稀疏矩阵、行数,列数
//输出:在屏幕上以行列的形式输出矩阵
{
int i = 0, j = 0, k = 0;
for (i = 0; i < a->m; i++)
{
for (j = 0; j < a->n; j++)
{
if (i == a->data[k].i && j == a->data[k].j)
{
printf("%d ", a->data[k].v);
k++;
}
else
printf("%d ", 0);
}
printf("\n");
}
}
本文深入探讨了特殊矩阵与稀疏矩阵的压缩存储方式,并以三元组表示稀疏矩阵为例,详细介绍了如何进行矩阵转置操作。通过算法分析,对比了稀疏矩阵与普通矩阵在转置过程中的效率差异。最后,提供了一个完整的C程序实例,展示了如何使用稀疏矩阵结构进行矩阵运算。
3256

被折叠的 条评论
为什么被折叠?



