特殊矩阵、稀疏矩阵表示方式(三元组、伪地址法、邻接表示、十字链式)

一、概念

严版数据结构:特殊矩阵相同元素或者零元素在矩阵中的分布存在一定规律的矩阵,反之称为稀疏矩阵

国外:矩阵中绝大多数元素都为0的矩阵称为稀疏矩阵。

二、特殊矩阵存储

一般的特殊矩阵是:对称矩阵、上三角矩阵、下三角矩阵、对角矩阵。

特殊矩阵存储这里列,上、下三角矩阵的存储。对称矩阵是按角对角线对称。

由对称矩阵A[i][j] = A[j][i],所以我们只需要保存一份即可,所需储存空间为(1+n)*n/2, 需要保存的元素为:

A(0,0) 
A(1,0) A(1,1)
A(2,0) A(2,1) A(2,2)   
....
A(n,0) A(n,1) A(n,2) .... A(n,n)

按照行优先来存储,保存在一维数组中。

分析:矩阵A中要储存元素个数是n(n+1)/2个,因为每行成等差数列。

结果如下:每一个元素对应一维数组的位置  i*(i+1)/2+j ,  i 表示行数,j 表示列数。

保存元素:A(0,0) A(1,0) A(1,1)  ...   A(n-1,0)   A(n-1,1)    A(n-1,2) .... A(n-1,n-1)
数组下标:   0      1      2    ...  n*(n-1)/2  n*(n-1)/2+1  n*(n-1)/2+2   n*(n+1)/2-1
#include<stdio.h>
int MaxSize;
int A[10][10];
int saveArr[100];
//初始化数组
void init() {
	for(int i=0; i<MaxSize; ++i) {
		for(int j=0; j<MaxSize; ++j) {
			if(i>j) {
				A[i][j]=i;
			} else if(i<j) {
				A[i][j]=j;
			} else {
				A[i][j]=0;
			}
		}
	}
	printf("很明显这是一个对称矩阵\nA:\n");
	for(int i=0; i<MaxSize; i++) {
		for(int j=0; j<MaxSize; j++) {
			printf("%d ",A[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

//存储对称矩阵的下三角。
void save() {
	int i,j,temp;
	int k=0;
	for(i=0; i<MaxSize; ++i) {
		for(j=0; j<MaxSize; ++j) {
			if(i>=j) {
				saveArr[i*(i+1)/2+j]=A[i][j];
				printf("%d ",A[i][j]);
			}
		}
		printf("\n");
	}
	printf("\n一维数组中存入的数据\n");
	for(i=0; i<(MaxSize*(MaxSize+1)/2); i++) {  //如果是n维矩阵,则为n*(n+1)/2
		printf("%d ",saveArr[i]);
	}

}

int main() {
	scanf("%d",&MaxSize);
	init();
	save();
}

三、三元组法表示稀疏矩阵

稀疏矩阵中的相同元素C,假设C是0,在矩阵中的分布不像在特殊矩阵中那么有规律,所以我们用数据结构将C存起来,并保存原始C在稀疏矩阵的位置信息。

三元组数据结构为一个长度为n,表内每个元素都有3个分量的线性表,其中3个分量分别为值、行下标、列下标。元素结构体定义如下:

typedef struct Node{
	int data; //储存数据 
	int line; //行下标 
	int row;  //列下标 
}Trimat;

一般我们可以用二维数组代替,即int A[maxterm+1][3],注意如果data为float类型,则 line或row 使用时,需要使用int进行强制转换。

例子:A矩阵如下:

0 0 0 1
0 0 3 2 
1 0 0 0
0 2 0 0

则三元组表示为:

  元素值  行下标  列下标
0    5      4      4    //第一行,元素值表示该矩阵中稀疏元素的个数,行下标值该矩阵的行数,列下标指该矩阵的列数。
1    1      0      3
2    3      1      2
3    2      1      3
4    1      2      0
5    2      3      1

创建代码,就不写了,直接一个循环遍历矩阵,看那个不是0就按上述格式加入到结构体数组中。

四、伪地址表示稀疏矩阵

伪地址即元素在矩阵中按照行优先或者列优先储存相对位置。伪地址法每一行只有两个储存单元,一个用来存放矩阵元素值,另一个用来存放伪地址。这种方法需要2N个储存单元,N为非0元素的个数,对于一个m*n的稀疏矩阵A,元素A[i][j]的伪地址计算方法伪n*i+j。

0 0 0 1
0 0 3 2 
1 0 0 0
0 2 0 0

伪地址分别是:3,6,7,8,13

五、稀疏矩阵的链式储存

1.邻接表表示法(节约空间)

将矩阵种每一行非零元素串成一个链表,链表结点中有两个分量,分别表示该结点对应的元素值列下标

typedef struct Node{
	int data; //储存数据 
	int row;  //列下标 
        struct Node *next;
}Trimat[100];

具体实现过于简单,循环遍历矩阵,为每一行的非零元素在 Trimat[i] 中创建单链表即可,这里没有专门的头结点。

2.十字链表表示法

矩阵的每一行用一个带头结点的链表表示,每一列用一个带头结点的链表表示,这种储存结构中有5个分量:行分量,列分量、数据分量、以及指向两头结点的指针。

普通结点定义:

typedef struct node{
    int row,col;
    struct node *right,*down;
    int data;
}Node;

头结点定义:

typedef struct{
    Node *rhead,*chead;
    int m , n , k;
}CrossList;

 

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值