C语言——一些特殊矩阵的处理(稀疏矩阵)

前言

本篇给大家介绍一些特殊矩阵的存储。
ps:比较短小。

一、特殊矩阵的压缩存储

1.n阶对称矩阵:aij=aji

矩阵标号:a11,a12,…,ann
首先明确:
(1)保存矩阵的下三角或上三角部分即可(包括对角线)
(2)这里选择保存下三角,下三角元素满足i>=j
(3)需保存个数=n(n+1)/2 ,根据个数分配空间
(4)假定以行序为主,顺序存储到SA[1…n(n+1)/2],aij保存到了SA[k]里,即可分析出ij的关系
①当aij在下三角,i>=j
前i-1行共有元素i(i-1)/2个,第i行中,aij是第j个数据元素,故aij的序号为k=i(i-1)/2 + j
②当aij在上三角,i<j,要访问它时,访问下三角对称的元素即可
上三角的aij=下三角的aji,根据下三角aji的序号找上三角的aij的序号即可

		最终得公式;i>= j    K=A[i,j] = SA[i(i-1)/2 + j]
					i<j		K=A[i,j] = SA[j(j-1)/2 + i]
		此公式称为在SA中的映像函数,或下标转换公式

2.三对角矩阵:除去三条对角线外,其余元素都是0

明确:
(1)元素aij在三对角的条件:|i-j|<=1
(2)三对角的元素个数:3n-2
(3)假定以行序为主,顺序存储到SA[1…3n-2]中,aij保存到了SA[k]里,即可分析出ij的关系
任意元素aij在SA中的序号:K=(3(i-1)+(j-i+2)=2i+j-2

由于以上两个矩阵能通过映像函数计算aij的位置,尽管是压缩存储,但也能进行随机访问

二、稀疏矩阵的压缩

1.三元组表

1.稀疏矩阵:
		零元素很多,非零元素很少,且非零元素在矩阵的位置没有特定的规律
	注:稀疏矩阵没有一个明确的定义,只是从形式上来看,非零元素的个数栈元素总数的比例低于某特定的阈值
由于非零元素很少,只需保存这些非零元素,没有保存的都是零元素。为了标明每个非零元素在矩阵中的位置,我们以(行、列、值)形式
的三元组形式来保存非零元素。
所有非零元素的三元组序列加上矩阵的行数和列数,称为三元组表

2.三元组顺序表

1.定义:分配连续的存储空间,保存稀疏矩阵中的三元组表
注:首先需要一个足够大的三元组数组空间,将非零元素的三元组按行序优先的次序保存在数组中,再就是矩阵的行数、列数和非零元素的个数
这样就能唯一的确定稀疏矩阵,逻辑上和物理上就对应起来了
在这里插入图片描述
2.数据类型
(1)假定非零元素的个数最大值为10000,定义常量MAXSIZE=10000
(2)定义三元组的结构类型triple,包括非零元素的行位置、列位置、元素值三个属性
(3)定义三元组顺序表的结构类型TSMatrix,包括大型为MAXISZE的三元组数组、行数、列数和非零元素个数几个属性

#define MAXSIZE 10000//假定非零元素的个数最大值为10000,定义常量MAXSIZE=10000
typedef struct
{
    
    
	int i,j;//非零元素行、列下标
	ElemType e; //非零元素值 
}Triple;//定义三元组
typedef struct
{
    
    
	Triple data[MAXSIZE+1];
	int mu,nu,tu;
}TSMatrix;//定义三元组表 

3.十字链表
在这里插入图片描述

解释:每行非零元素的三元组结点构成一个单链表,需要行头指针数组来保存所有行的头指针,同样需要一个列头指针数组。
同时,每列非零元素的三元组结点构成一个单链表。为管理两个头指针数组,同时提供完整的矩阵信息,使用一个结构型数据,包含两个头指针数组的信息等

我们称这种物理结构称为十字链表,非常形象的表示了每个非零元素的水平方向关系、行关系,以及垂直方向的关系,列关系。这两种关系十字交叉,故称为十字链表

//用C语言定义十字链表表类型
typedef struct OLNode//三元组结点定义 
{
    
    
	int i,j;//非零元素行列位置
	ElemType e;
	struct OLNode *right,*down; 
}OLNode,*OLink;

typedef struct//十字链表类型定义 
{
    
    
	OLink *rhead,*chead;//行列头指针数组
	int mu,nu,tu;//稀疏矩阵的行数、列数和非零元素个数 
}CrossList; 

三、稀疏矩阵的运算(转置算法)

矩阵转置算法:所得T以行序优先
在这里插入图片描述

//算法:时间复杂度:O(M.tu*M.nu) 
void TransMatrix1 (TSMatrix M,TSMatrix &T)
{
    
    
	T.mu = M.nu;
	T.nu = M.mu;
	T.tu = M.tu;
	
	if (T.tu)
	{
    
    
		q = 1;//指示向T写时的位置
		for (col=1;col<=M.nu;col++)//扫描M的三元组M.nu次 
		{
    
    
			for (p=1;p<=M.tu;p++)//扫描M的长度为M.tu的三元表
			{
    
    
				if (M.data[q].i==col)//找到一个符合条件的三元组
				{
    
    
					T.data[q].i = M.data[p].j;
					T.data[q].j = M.data[p].i;
					T.data[q].e = M.data[p].e;
					q++;
				} 
			} 
		} 
	}
}

总结

这篇确实短小,第一部分只做了文字说明,没有代码实现。
除了稀疏矩阵之外,如三对角矩阵等等。矩阵这块有很多算法,大家感兴趣可以去看看。有很多大佬的打包总结。
下一篇应该就是广义表啦~
ps:代码非原创
如有错误,欢迎指正。

猜你喜欢

转载自blog.csdn.net/qq_51308373/article/details/115243183