【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)

这篇具有很好参考价值的文章主要介绍了【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


稀疏矩阵是指矩阵中大多数元素为零的矩阵。从直观上讲,当非零元素个数低于总元素的30%时,这样的矩阵为稀疏矩阵。

1. 三元组表

1.1 三元组表的存储结构

稀疏矩阵的三元组表表示法是指只存储非零元素,同时存储该非零元素在矩阵中所处的行号和列号的位置信息。
【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)为方便处理,将稀疏矩阵中非零元素对应的三元组按“行序为主序”的一维结构体数组进行存放,将矩阵的每一行(行由小到大)的全部非零元素的三元组按列号递增存放,得到矩阵的三元组表
【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)
代码

# define MAXSIZE 1000				//设非零元素的个数最多为1000
/*三元组的存储结构*/
typedef struct {
	int row, col;					//该非零元素的行下标和列下标
	int e;							//该非零元素的值
}Triple;
/*三元组表的存储结构*/
typedef struct {
	Triple data[MAXSIZE + 1];		//非零元素的三元组表,下标从1开始
	int m, n, len;					//矩阵的行数、列数和非零元素的个数
}TSMatrix;

1.2 基于三元组表的矩阵转置

① 三元组表中的三元组行列互换。
② 三元组表重新按照行下标递增排序。

1.2.1 列序递增转置法
采用按照被转置矩阵三元组表A的列序递增的顺序进行转置,并依次送入转置后矩阵的三元组表B中。
【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)

/*转置:列序递增转置法*/
void TransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
	int i, j, k;
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len > 0) {
		j = 1;											//记录转置后的三元组在三元组表B中的下标值
		for (k = 1; k <= A->n; k++) {
			for (i = 1; i < A->len; i++) {				//从头至尾扫描三元组表A,寻找col值为k的三元组进行转置
				if (A->data[i].col == k) {
					B->data[j].row = A->data[i].col;
					B->data[j].col = A->data[i].row;
					B->data[j].e = A->data[i].e;
					j++;
				}
			}
		}
	}
}

1.2.2 一次快速转置法
只对三元组表A扫描一次,就使A中所有非零元的三元组“一次定位”直接放到三元组B中的正确位置上。

num[col]:用来存放三元组表A第col列中非零元素总个数
position[col]:用来存放转置前三元组表A中第col列中第一个非零元素在三元组表B中的存储位置(下标值)
position[1] = 1
position[col] = position[col - 1] + num[col - 1](col > 1)
【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)

/*一次定位快速转置法*/
void FastTransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
	int col, t, p, q;
	int num[MAXSIZE], position[MAXSIZE];
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len) {
		for (col = 1; col <= A->n; col++)				//初始化num数组
			num[col] = 0;
		for (t = 1; t <= A->len; t++)
			num[A->data[t].col]++;						//扫描三元组表A,求num数组
		position[1] = 1;
		for (col = 2; col < A->n; col++)				//根据num数组求position数组
			position[col] = position[col - 1] + num[col - 1];

		for (p = 1; p <= A->len; p++) {					//扫描三元组表A,实现转置
			col = A->data[p].col;
			q = position[col];
			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[col]++;							//表示该列的下一个非零元素
		}
	}
}

1.3 完整实现代码

# include<stdio.h>
# define MAXSIZE 1000				//设非零元素的个数最多为1000

/*三元组*/
/*三元组的存储结构*/
typedef struct {
	int row, col;					//该非零元素的行下标和列下标
	int e;							//该非零元素的值
}Triple;
/*三元组表的存储结构*/
typedef struct {
	Triple data[MAXSIZE + 1];		//非零元素的三元组表
	int m, n, len;					//矩阵的行数、列数和非零元素的个数
}TSMatrix;

/*根据数组创建三元组表*/
void CreateTSMatrix(TSMatrix* A, int arry[][7], int m, int n) {
	int i, j, k = 1;
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			if (arry[i][j] != 0) {
				A->data[k].row = i + 1;
				A->data[k].col = j + 1;
				A->data[k].e = arry[i][j];
				k++;
			}
		}
	}
	A->len = k - 1;
	A->m = m;
	A->n = n;
}

/*转置:列序递增转置法*/
void TransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
	int i, j, k;
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len > 0) {
		j = 1;											//记录转置后的三元组在三元组表B中的下标值
		for (k = 1; k <= A->n; k++) {
			for (i = 1; i < A->len; i++) {				//从头至尾扫描三元组表A,寻找col值为k的三元组进行转置
				if (A->data[i].col == k) {
					B->data[j].row = A->data[i].col;
					B->data[j].col = A->data[i].row;
					B->data[j].e = A->data[i].e;
					j++;
				}
			}
		}
	}
}

/*一次定位快速转置法*/
/* num[col]用来存放三元组表A第col列中非零元素总个数
   position[col]用来存放转置前三元组表A中第col列中第一个非零元素在三元组表B中的存储位置(下标值)
   position[col]=position[col-1]+num[col-1](col>1) */
void FastTransposeTSMatrix(TSMatrix* A, TSMatrix* B) {
	int col, t, p, q;
	int num[MAXSIZE], position[MAXSIZE];
	B->m = A->n;
	B->n = A->m;
	B->len = A->len;
	if (B->len) {
		for (col = 1; col <= A->n; col++)				//初始化num数组
			num[col] = 0;
		for (t = 1; t <= A->len; t++)
			num[A->data[t].col]++;						//扫描三元组表A,求num数组
		position[1] = 1;
		for (col = 2; col < A->n; col++)				//根据num数组求position数组
			position[col] = position[col - 1] + num[col - 1];

		for (p = 1; p <= A->len; p++) {					//扫描三元组表A,实现转置
			col = A->data[p].col;
			q = position[col];
			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[col]++;							//表示该列的下一个非零元素
		}
	}
}

/*根据三元组表输出稀疏矩阵*/
void Display(TSMatrix* A) {
	int i, j, k = 1;
	for (i = 1; i <= A->m; i++) {
		for (j = 1; j <= A->n; j++) {
			if (i == A->data[k].row && j == A->data[k].col) {
				printf("%3d", A->data[k].e);
				k++;
			}
			else
				printf("  0");
		}
		printf("\n");
	}
}

int main() {
	int M[6][7] = { {0,12,9,0,0,0,0},
				{0,0,0,0,0,0,0},
				{-3,0,0,0,0,14,0},
				{0,0,24,0,0,0,0},
				{0,18,0,0,0,0,0},
				{15,0,0,-7,0,0,0} };
	TSMatrix A, B, C;
	CreateTSMatrix(&A, M, 6, 7);
	TransposeTSMatrix(&A, &B);
	printf("列序递增转置法:\n");
	Display(&B);
	FastTransposeTSMatrix(&A, &C);
	printf("\n一次定位快速转置法:\n");
	Display(&C);
	return 0;
}

1.4 运行结果

【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)

2. 十字链表

2.1 十字链表的存储结构

十字链表是稀疏矩阵的链式存储法。矩阵的每一个非零元素用一个结点表示,该结点除了(row,col,vaule)以外,还要添加两个链域:right 用于链接同一行中的下一个非零元素,down 用于链接同一列中的下一个非零元素。
【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)代码实现

/*十字链表的存储结构*/
typedef struct OLNode {
	int row, col;						//非零元素的行和列下标
	int vaule;
	struct OLNode* right, * down;		//非零元素所在行表、列表的后继链域
}OLNode, *OLink;

typedef struct {
	OLink* row_head, * col_head;		//行、列链表的头指针向量
	int m, n, len;						//稀疏矩阵的行数、列数、非零元素个数
}CrossList;

参考:耿国华《数据结构——用C语言描述(第二版)》

更多数据结构内容关注我的《数据结构》专栏:https://blog.csdn.net/weixin_51450101/category_11514538.html?spm=1001.2014.3001.5482文章来源地址https://www.toymoban.com/news/detail-414982.html

到了这里,关于【数据结构】稀疏矩阵的压缩存储(三元组表、十字链表)(C语言)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】数组和字符串(五):特殊矩阵的压缩存储:稀疏矩阵——压缩稀疏行(CSR)

    【数据结构】数组和字符串(一):矩阵的数组表示   矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造

    2024年02月05日
    浏览(54)
  • 【数据结构】数组(稀疏矩阵、特殊矩阵压缩、矩阵存储、稀疏矩阵的快速转置、十字链表)

    前几期期链接: 【数据结构】栈与队列的概念和基本操作代码实现 【数据结构】树与二叉树的概念与基本操作代码实现 k维数组的定义: k 维数组 D = { a j 1 , j 2 , . . . , j k } k维数组D={ a_{j_1, j_2, ..., j_k} } k 维数组 D = { a j 1 ​ , j 2 ​ , ... , j k ​ ​ } k 0 称为数组的维数,

    2024年04月09日
    浏览(140)
  • 数据结构-拓展突破-特殊矩阵(对称矩阵,三角矩阵,三对角矩阵,稀疏矩阵)的压缩存储)

    对称矩阵的定义: 若n阶方阵中任意一个元素a,都有a(i,j)=a(j,i)则该矩阵为对称矩阵 也就是说对称矩阵的元素关于对角线对称。对角线上半部分称为上三角区,下半部分称为下三角区。 对称矩阵的压缩存储策略:只存储主对角线+下三角区(或主对角线+上三角区) 可以定义一维数

    2023年04月08日
    浏览(63)
  • 数据结构·练习·三元组表法实现稀疏矩阵的转置

    一、问题描述 一个mxn的矩阵A,它的转置矩阵B是一个nxm矩阵,且A[i][j]=B[j][i],0=i=m-1,0=j=n-1,即A的行是B的列,A的列是B的行。 用三元组表对稀疏矩阵进行压缩存储,再进行时间复杂度O(n)的快速转置,最后输出稀疏矩阵。 其中m=4,n=5 二、算法概述 1、问题分析 1)压缩 2)转置

    2024年02月04日
    浏览(45)
  • 【C 数据结构】以三元组表形式表示稀疏矩阵,实现两个矩阵的加法、减法

    目的:以三元组表形式表示稀疏矩阵,实现两个矩阵的加法、减法。 实验步骤 1. 定义三元组存储结构 2. 输入稀疏矩阵:首先应输入矩阵的行数、列数和非零项的数目,并判别给出的两个矩阵的行、列数对于所要求进行的运算是否匹配。可设矩阵的行数和列数均不超过20。接

    2024年02月12日
    浏览(49)
  • 数据结构第七周 :(稀疏矩阵快速转置 + 简单文本编辑器 + 三元组的矩阵加法 + 九宫格数独游戏 + 数组主元素 + 螺旋数字矩阵 + 蛇形矩阵)

    【问题描述】 稀疏矩阵的存储不宜用二维数组存储每个元素,那样的话会浪费很多的存储空间。所以可以使用一个一维数组存储其中的非零元素。这个一维数组的元素类型是一个三元组,由非零元素在该稀疏矩阵中的位置(行号和列号对)以及该元组的值构成。而矩阵转置就

    2023年04月21日
    浏览(43)
  • 【数据结构】矩阵的压缩存储

    5.1 普通矩阵的存储 用二维数组存储 分为行优先和列优先: 行优先:优先存放一行的数据。 列优先:优先存放一列的数据。 注意下标是从0还是1开始的! 5.2 对称矩阵的存储 对称矩阵定义 若n阶方阵中任意一个元素 a i , j a_{i,j} a i , j ​ 都有 a i , j = a j , i a_{i,j}=a_{j,i} a i , j

    2024年03月18日
    浏览(57)
  • 【数据结构与算法】 完成用十字链表存储的稀疏矩阵的加法运算

       Qestion:   完成用十字链表存储的稀疏矩阵的加法运算。 获取两个稀疏矩阵总有多少个非零元素,记作 cnt 。 当 cnt 不为零时一直循环,每循环一次 i++ ,也就是行循环,每循环一次就转移至下一行。 先从第一行开始循环,使得两个工作指针 p 、 q 分别指向两个稀疏矩阵

    2024年02月13日
    浏览(45)
  • 【数据结构】特殊矩阵的压缩存储

    🌈 自在飞花轻似梦,无边丝雨细如愁 🌈   🌟 正式开始学习数据结构啦~此专栏作为学习过程中的记录 🌟 数组是由n个相同类型的数据元素所构成的有限序列 数组和线性表的关系: 数组是线性表的推广:一维数组可以看做是一个线性表,而对于二维数组而言,可以看成是有

    2024年02月11日
    浏览(47)
  • 数据结构--特殊矩阵的压缩存储

    各数组元素大小相同,且物理上连续存放。 数组元素a[i]的存放地址= LOC + i * sizeof(ElemType) ( 0 ≤ i 10 ) (0le i 10) ( 0 ≤ i 10 ) 注:除非题目特别说明,否则数组 下标默认从 0 开始 color{red}下标默认从0开始 下标默认从 0 开始 注意审题 ! 易错 ! color{purple}注意审题!易错! 注意审题

    2024年02月16日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包