稀疏数组及转置稀疏数组实现(C语言)

稀疏矩阵定义:

对一个m*n的矩阵,设s为矩阵元素的总和,有s=m*n,设t为矩阵中非零元素的总和,满足t<<s的矩阵成为稀疏矩阵

稀疏矩阵中每个非零元素及其对应的行下标和列下标构成一个三元组,稀疏矩阵中所有这样的三元组构成一个三元组线性表

稀疏矩阵的压缩存储结构主要有三元组顺序表三元组链表两大类。其中,三元组链表中又包括一般链表行指针数组的链表行列指针的十字链表存储结构等。


本篇介绍的是三元组顺序表的C语言实现。在以下代码解释中,二维数组等价于稀疏矩阵,稀疏矩阵等价于三元组顺序表。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#define Max_Node_Num 100
#define Max_Row 11
#define Max_Col 11

typedef struct{
	unsigned int row;  //行号
	unsigned int col;  //列号
	int data;  //元素值 
}Struct_DataNode;  //数据结点结构体 

typedef struct{
	Struct_DataNode DataNode[Max_Node_Num]; 
	unsigned int MatrixRow, MatrixCol, TotalDataNodeNum;  //二维数组行数,列数,非零元素个数 
}Struct_SparseArr;  //稀疏矩阵结构体 

int main(int argc, char *argv[]) {
	//定义稀疏矩阵、转置稀疏矩阵
	Struct_SparseArr OriSparseArr, TraSparseArr;
	//定义期间要用到的变量 -> i/j/temp:循环变量
	int i, j, temp;
	
	//初始化稀疏矩阵、转置稀疏矩阵
	memset(&OriSparseArr, 0x00, sizeof(OriSparseArr));
	memset(&TraSparseArr, 0x00, sizeof(TraSparseArr));
	
	//定义二维数组
	int Ori2DArr[Max_Row][Max_Col] = {
		{0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	};
	
	//将二维数组行数、列数赋值给稀疏矩阵结构体
	OriSparseArr.MatrixRow = Max_Row;
	OriSparseArr.MatrixCol = Max_Col;
	
	//遍历二维数组 -> 打印二维数组、将二维数组有效数据存入稀疏矩阵
	printf("原始二维数组:\n");
	for(i = 0; i < Max_Row; i++){
		for(j = 0; j < Max_Col; j++){
			printf("%3d",Ori2DArr[i][j]);
			
			//如果二维数组元素值不为0,存入稀疏矩阵中 
			if(Ori2DArr[i][j]){
				OriSparseArr.DataNode[OriSparseArr.TotalDataNodeNum].row = i;
				OriSparseArr.DataNode[OriSparseArr.TotalDataNodeNum].col = j;
				OriSparseArr.DataNode[OriSparseArr.TotalDataNodeNum].data = Ori2DArr[i][j];
				OriSparseArr.TotalDataNodeNum++;  //二维数组非零元素个数加一 
			}
		}
		printf("\n");
	} 
	
	//打印稀疏矩阵
	printf("稀疏矩阵:\n");
	for(i = 0; i < OriSparseArr.TotalDataNodeNum; i++){
		printf("[%d,%d,%d]\n", OriSparseArr.DataNode[i].row, OriSparseArr.DataNode[i].col, OriSparseArr.DataNode[i].data);
	} 
	
	//转置稀疏矩阵 
	//稀疏矩阵行号 -> 转置稀疏矩阵列号;稀疏矩阵列号 -> 转置稀疏矩阵行号;非零元素个数赋值
	TraSparseArr.MatrixCol = OriSparseArr.MatrixRow;
	TraSparseArr.MatrixRow = OriSparseArr.MatrixCol;
	TraSparseArr.TotalDataNodeNum = OriSparseArr.TotalDataNodeNum;
	
	//遍历稀疏矩阵进行转置操作
	//稀疏矩阵个数非0时进行转置操作 
	//保证转置稀疏矩阵第一列升序排列 
	printf("转置稀疏矩阵:\n");
	if(OriSparseArr.TotalDataNodeNum){
		for(i = 0, temp = 0; i < TraSparseArr.MatrixRow; i++){
			for(j = 0; j < TraSparseArr.TotalDataNodeNum; j++){
				if(i == OriSparseArr.DataNode[j].col){
					TraSparseArr.DataNode[temp].row = OriSparseArr.DataNode[j].col;
					TraSparseArr.DataNode[temp].col = OriSparseArr.DataNode[j].row;
					TraSparseArr.DataNode[temp].data = OriSparseArr.DataNode[j].data;
					printf("[%d,%d,%d]\n", TraSparseArr.DataNode[temp].row, TraSparseArr.DataNode[temp].col, TraSparseArr.DataNode[temp].data);
					temp++;
				}
			}
		}
	} 
	
	//将转置稀疏矩阵 转 转置二维数组
	printf("转置二维数组:\n");
	for(i = 0, temp = 0; i < TraSparseArr.MatrixRow; i++){
		for(j = 0; j < TraSparseArr.MatrixCol; j++){
			if(i == TraSparseArr.DataNode[temp].row && j == TraSparseArr.DataNode[temp].col){
				printf("%3d",TraSparseArr.DataNode[temp].data);
				temp++;
			}
			else
				printf("%3d", 0);
		}
		printf("\n");
	} 
	return 0;
}

本篇参考:

C语言数据结构之稀疏矩阵(一)

数据结构——使用C语言(第五版)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要用文件表示三元数组稀疏矩阵的快速,可以先将三元组存储到文件中,然后按列读取文件,将每个元素插入到后的矩阵中。具体步骤如下: 1. 定义三元组结构体,包含行、列和值三个成员变量。 ``` typedef struct { int row; // 行 int col; // 列 int val; // 值 } Triple; ``` 2. 读取三元组稀疏矩阵并存储到文件中。 ``` FILE *fp1 = fopen("matrix.txt", "r"); FILE *fp2 = fopen("triples.txt", "w"); int m, n, t; fscanf(fp1, "%d%d%d", &m, &n, &t); fprintf(fp2, "%d %d %d\n", n, m, t); // 后的矩阵行列数和非零元素个数与原矩阵相反 for (int i = 0; i < t; i++) { int row, col, val; fscanf(fp1, "%d%d%d", &row, &col, &val); fprintf(fp2, "%d %d %d\n", col, row, val); // 行列交换 } fclose(fp1); fclose(fp2); ``` 3. 读取后的三元组稀疏矩阵文件,并按列插入到后的矩阵中。 ``` fp2 = fopen("triples.txt", "r"); fscanf(fp2, "%d%d%d", &n, &m, &t); int *row = (int*)malloc(t * sizeof(int)); int *col = (int*)malloc(t * sizeof(int)); int *val = (int*)malloc(t * sizeof(int)); for (int i = 0; i < t; i++) { fscanf(fp2, "%d%d%d", &col[i], &row[i], &val[i]); // 行列交换 } fclose(fp2); int *start = (int*)malloc((n + 1) * sizeof(int)); int *num = (int*)malloc((n + 1) * sizeof(int)); memset(num, 0, (n + 1) * sizeof(int)); for (int i = 0; i < t; i++) { num[col[i]]++; // 统计每列非零元素个数 } start[1] = 0; for (int i = 2; i <= n; i++) { start[i] = start[i - 1] + num[i - 1]; // 计算每列非零元素的起始位 } for (int i = 0; i < t; i++) { int j = start[col[i]]++; row[j] = col[i]; col[j] = row[i]; val[j] = val[i]; } ``` 4. 输出后的三元组稀疏矩阵。 ``` printf("后的三元组稀疏矩阵:\n"); for (int i = 0; i < t; i++) { printf("%d %d %d\n", row[i], col[i], val[i]); } ``` 注意:在实际应用中,需要根据具体情况进行优化,如使用链式前向星优化存储和计算,避免重复读写文件等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值