1.稀疏矩阵:指由大量0和少量其他元素组成的矩阵
2.放弃传统存储方式的原因:矩阵的0太多,导致二维数组开辟的空间会被大量浪费
3.稀疏矩阵的存储方式:三元组
typedef struct
{
int line;
int row;
int val;
}trinode;
typedef struct
{
trinode data[100];
int linenum;
int rownum;
int num;
}tritable;
代码解释:先定义非0元素信息存储结构体,line表示元素的行数,row代表元素的列数,val代表此元素的值,那么我们的存储思路就很明显了:只存储非0值的信息,在需要打印的时候在记录位置打印非0值,其余位置打印0,而第二个结构体就是三元组存储方式的具体实现,首先它有一个结构体数组用来储存非0元素的具体信息,并且存储了稀疏矩阵的行数,列数以及非0元素的个数
下面来看交换函数
void triswap(tritable target, tritable* room)
{
room->linenum = target.rownum;
room->rownum = target.linenum;
room->num = target.num;
int j = 1;
if (room->num > 0)
{
j = 1;
for (int x = 1; x <= target.rownum; x++)
{
for (int y = 1; y <= target.num; y++)
{
if (x == target.data[y].row)
{
room->data[j].line = target.data[y].row;
room->data[j].row = target.data[y].line;
room->data[j].val = target.data[y].val;
j++;
}
}
}
}
}
整体思路:首先定义一个传入地址的结构体room,用于存储转置后的矩阵,首先将目标矩阵的行数和列数作为空间矩阵的列数与行数,因为转置不改变元素个数,所以直接将目标矩阵的非0元素个数赋给空间矩阵,然后制作空间矩阵的三元组(data[0]不参与计算因为不存在有0个未知元素),而我们的空间矩阵赋值以行数为基准,而这个行数就是目标矩阵的列数,在每一行的元素遍历中遍历target的三元组,当空间矩阵的行数等于目标矩阵的列数时,将目标矩阵的该元素的行列交叉赋值给空间矩阵,值直接赋给空间矩阵
完整测试代码
#include<stdio.h>
#include<malloc.h>
typedef struct
{
int line;
int row;
int val;
}trinode;
typedef struct
{
trinode data[100];
int linenum;
int rownum;
int num;
}tritable;
void triswap(tritable target, tritable* room)
{
room->linenum = target.rownum;
room->rownum = target.linenum;
room->num = target.num;
int j = 1;
if (room->num > 0)
{
j = 1;
for (int x = 1; x <= target.rownum; x++)
{
for (int y = 1; y <= target.num; y++)
{
if (x == target.data[y].row)
{
room->data[j].line = target.data[y].row;
room->data[j].row = target.data[y].line;
room->data[j].val = target.data[y].val;
j++;
}
}
}
}
}
int main()
{
tritable s;
printf("请输入稀疏矩阵的行数、列数和非零元素个数(以空格隔开):");
scanf_s("%d%d%d", &s.linenum, &s.rownum, &s.num);
int val;
val = s.num;
int i;
for (i = 1; i <= val; i++)
{
printf("第%d个元素<行号,列号,值>:", i);
scanf_s("%d%d%d", &s.data[i].line, &s.data[i].row, &s.data[i].val);
}
printf("转置前的三元组<行号,列号,值>:\n");
for (i = 1; i <= s.num; i++)
{
printf("%d ,%d ,%d \n", s.data[i].line, s.data[i].row, s.data[i].val);
}
tritable t;
triswap(s, &t);
printf("转置后的三元组<行号,列号,值>:\n");
for (i = 1; i <= t.num; i++)
{
printf("%d ,%d ,%d \n", t.data[i].line, t.data[i].row, t.data[i].val);
}
return 0;
}
以下为快速转置方法
void triswap(tritable target, tritable* room)
{
int arr1[100];
int arr2[100];
room->linenum = target.rownum;
room->rownum = target.linenum;
room->num = target.num;
if (room->num > 0)
{
for (int x = 1; x < target.rownum; x++)
{
arr1[x] = 0;
}
for (int x = 1; x < target.num; x++)
{
arr1[target.data[x].row - 1]++;
}
arr2[1] = 1;
for (int x = 2; x <= target.rownum; x++)
{
arr2[x] = arr2[x - 1] + arr1[x - 1];
}
for (int x = 1; x <= target.num; x++)
{
int t = target.data[x].row - 1;
int pos = arr2[t];
room->data[pos].line = target.data[x].row;
room->data[pos].row = target.data[x].line;
room->data[pos].val = target.data[x].val;
arr2[t]++;
}
}
}
其中arr1储存的是目标矩阵每列的非0元素个数,而arr2储存的是每列第一个非0元素在目标数组中的序号,而最终转换环节就是将目标数组的循环值中的列数赋给中间变量,然后将遍历目标数组改为直接跳到第一个非0元素开始赋值
#include<stdio.h>
#include<malloc.h>
typedef struct
{
int line;
int row;
int val;
}trinode;
typedef struct
{
trinode data[100];
int linenum;
int rownum;
int num;
}tritable;
void triswap(tritable target, tritable* room)
{
int arr1[100];
int arr2[100];
room->linenum = target.rownum;
room->rownum = target.linenum;
room->num = target.num;
if (room->num > 0)
{
for (int x = 1; x < target.rownum; x++)
{
arr1[x] = 0;
}
for (int x = 1; x < target.num; x++)
{
arr1[target.data[x].row - 1]++;
}
arr2[1] = 1;
for (int x = 2; x <= target.rownum; x++)
{
arr2[x] = arr2[x - 1] + arr1[x - 1];
}
for (int x = 1; x <= target.num; x++)
{
int t = target.data[x].row - 1;
int pos = arr2[t];
room->data[pos].line = target.data[x].row;
room->data[pos].row = target.data[x].line;
room->data[pos].val = target.data[x].val;
arr2[t]++;
}
}
}
int main()
{
tritable s;
printf("请输入稀疏矩阵的行数、列数和非零元素个数(以空格隔开):");
scanf_s("%d%d%d", &s.linenum, &s.rownum, &s.num);
int val;
val = s.num;
int i;
for (i = 1; i <= val; i++)
{
printf("第%d个元素<行号,列号,值>:", i);
scanf_s("%d%d%d", &s.data[i].line, &s.data[i].row, &s.data[i].val);
}
printf("转置前的三元组<行号,列号,值>:\n");
for (i = 1; i <= s.num; i++)
{
printf("%d ,%d ,%d \n", s.data[i].line, s.data[i].row, s.data[i].val);
}
tritable t;
triswap(s, &t);
printf("转置后的三元组<行号,列号,值>:\n");
for (i = 1; i <= t.num; i++)
{
printf("%d ,%d ,%d \n", t.data[i].line, t.data[i].row, t.data[i].val);
}
return 0;
}