table of Contents
sparse matrix
Suppose m n-matrix, there t is non-zero elements, so t = S / m n-, when, s <= 0.05 when this matrix is called a sparse matrix, simple understanding is particularly low nonzero matrix
//一般矩阵a
1 2 3
a= 4 5 6
7 8 9
//稀疏矩阵s
0 0 0 0 0
0 2 0 0 5
s= 0 0 3 0 0
0 0 0 0 4
Transposed matrix
A m * n matrix transpose matrix becomes n * m
//3*2的矩阵-转置前
1 2
4 5
7 8
//转置后变为2*3
1 4 7
2 5 8
The table for each element of the matrix and the transposed table opposite the original, for example 4 above subscript before permutation is (2,1), transposed becomes (1,2);
Matrix compact storage - triples order table
The reason why the introduction of triple sequence table, because, for sparse matrix, the traditional method of storage will result in waste of storage space
0 12 9 0 0 0 0
0 0 0 0 0 0 0
-3 0 0 0 0 14 0
M= 0 0 24 0 0 0 0
0 18 0 0 0 0 0
15 0 0 -7 0 0 0
//上面矩阵用三元组表示
i j v
1 2 12
1 3 9
3 1 -3
3 6 14
4 3 24
5 2 18
6 1 15
6 4 -7
typedef struct
{
int i,j; //行坐标、列坐标
ElemType e; //元素
}Triple;
typedef struct
{
Triple date[MAXSIZE+1]; //0不存储元素
int mu,nu,tu; //行数、列数、非零元个数
}TSMatrix;
Sparse matrix transpose
Through each matrix transpose algorithm a conventional method, the index value which can be exchanged
for(col=1;col<=nu;col++)
{
for(row=1;row<=mu;row++)
{
T[col][row]=M[row][col]
}
}
//时间复杂度 : O(nu*mu)
Using the triple sequential table storing sparse matrix transpose order to achieve the above algorithm can not be apparent, the two methods described below:
The first: a column permutation sequence based sequence
//置换前 存储位置
i j v
1 2 12 -> M.date[1]
1 3 9 -> M.date[2]
3 1 -3 -> M.date[3]
3 6 14 -> M.date[4]
4 3 24 -> M.date[5]
5 2 18 -> M.date[6]
6 1 15 -> M.date[7]
6 4 -7 -> M.date[8]
//置换后 存储位置
i j v
1 3 -3 -> T.date[1]
1 6 15 -> T.date[2]
2 1 12 -> T.date[3]
2 5 18 -> T.date[4]
3 1 9 -> T.date[5]
3 4 24 -> T.date[6]
4 6 -7 -> T.date[7]
6 3 14 -> T.date[8]
void TransposeSMatrix(TSMatrix *T1,TSMatrix *T2)
{
T2->mu=T1->nu;T2->nu=T1->mu;T2->tu=T1->tu;
if(T1->tu)
{
int q=1,col,p;
for(col=1;col<=T1->nu;col++) //矩阵列循环
{
for(p=1;p<=T1->tu;p++) //遍历所有元素
{
if(T1->date[p].j==col) //当元素在col列时
{
T2->date[q].i=T1->date[p].j;
T2->date[q].j=T1->date[p].i;
T2->date[q].e=T1->date[p].e;
q++;
}
}
}
}
}
//上述代码,当矩阵运算为满时,即tu=mu*nu,其时间复杂度为O(nu*nu*mu)
//这种情况与经典算法相比,虽节省了存储空间,但是效率较低
The second: Fast transpose
The first algorithm is by traversing all the elements of the index, to determine its position in the array transposition, quickly transposed idea is that first a predetermined nonzero element of each column in the array corresponding to date transposed in position; thus requires two auxiliary array
num []: used to store the number of nonzero elements in each column
cpot []: holding the first nonzero element of the array position transposed date of
num [] array of values of good demand, only need to traverse once all the elements to
for(t=1;t<=T1->tu;t++)
++num[T1->date[t].j];
For cpot [], there is a rule
col 1 2 3 4 5 6 7
num[col] 2 2 2 1 0 1 0
cpot[col] 1 3 5 7 8 8 9
//规律
copt[1]=1
copt[col]=copt[col-1]+num[col-1]
Code:
void FastTransposeSMatrix(TSMatrix *T1,TSMatrix *T2)
{
int num[T1->nu],cpot[T1->nu];
int col,p,q,t;
T2->mu=T1->nu;T2->nu=T1->mu;T2->tu=T1->tu;
if(T1->tu)
{
//初始化每列非零元个数为0
for(col=1;col<=T1->nu;col++)
{
num[col]=0;
}
//求每列非零元个数
for(t=1;t<=T1->tu;t++)
{
++num[T1->date[t].j];
}
//求每列第一个非零元转置后的位置
cpot[1]=1;
for(col=2;col<=T1->nu;col++)
{
cpot[col]=num[col-1]+cpot[col-1];
}
//遍历所有元素
for(p=1;p<=T1->tu;p++)
{
col=T1->date[p].j; //获取列坐标
q=cpot[col]; //获取新位置
T2->date[q].i=T1->date[p].j;
T2->date[q].j=T1->date[p].i;
T2->date[q].e=T1->date[p].e;
++cpot[col]; //之所以这个地方要++,因为每列非零元可能不止一个
}
}
}
Complete code:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 12500 //非零元个数的最大值
typedef int ElemType;
typedef struct
{
int i,j;
ElemType e;
}Triple;
typedef struct
{
Triple date[MAXSIZE+1];
int mu,nu,tu;
}TSMatrix;
//输入元素
void Insert(TSMatrix *T)
{
printf("请依次输入行数i、列数j、非零元个数sum:\n");
int sum ;
scanf("%d%d%d",&T->mu,&T->nu,&sum);
T->tu=sum;
int x,y,num;
printf("请依次输入矩阵非零元的行坐标i、列坐标j、元素值x:\n");
printf("i j v\n");
for(int i=1 ;i<=sum;i++)
{
scanf("%d%d%d",&x,&y,&num);
T->date[i].i=x;
T->date[i].j=y;
T->date[i].e=num;
}
}
//第一种转置方法
void TransposeSMatrix(TSMatrix *T1,TSMatrix *T2)
{
T2->mu=T1->nu;T2->nu=T1->mu;T2->tu=T1->tu;
if(T1->tu)
{
int q=1,col,p;
for(col=1;col<=T1->nu;col++)
{
for(p=1;p<=T1->tu;p++)
{
if(T1->date[p].j==col)
{
T2->date[q].i=T1->date[p].j;
T2->date[q].j=T1->date[p].i;
T2->date[q].e=T1->date[p].e;
q++;
}
}
}
}
}
//输出矩阵非零元
void Show(TSMatrix *T)
{
printf("转置后的矩阵:\n");
printf("i j v\n");
for(int i=1;i<=T->tu;i++)
{
printf("%d %d %d\n",T->date[i].i,T->date[i].j,T->date[i].e);
}
}
//快速转置
void FastTransposeSMatrix(TSMatrix *T1,TSMatrix *T2)
{
int num[T1->nu],cpot[T1->nu];
int col,p,q,t;
T2->mu=T1->nu;T2->nu=T1->mu;T2->tu=T1->tu;
if(T1->tu)
{
//初始化每列非零元个数为0
for(col=1;col<=T1->nu;col++)
{
num[col]=0;
}
//求每列非零元个数
for(t=1;t<=T1->tu;t++)
{
++num[T1->date[t].j];
}
cpot[1]=1;
for(col=2;col<=T1->nu;col++)
{
cpot[col]=num[col-1]+cpot[col-1];
}
for(p=1;p<=T1->tu;p++)
{
col=T1->date[p].j;
q=cpot[col];
T2->date[q].i=T1->date[p].j;
T2->date[q].j=T1->date[p].i;
T2->date[q].e=T1->date[p].e;
++cpot[col];
}
}
}
int main()
{
TSMatrix T,T1,*q,*p;
p=&T;q=&T1;
Insert(p);
//测试第一种转置方法
TransposeSMatrix(p, q);
Show(q);
//测试快速转置
FastTransposeSMatrix(p, q);
Show(q);
}
/* 测试
请依次输入行数i、列数j、非零元个数sum:
6 7 8
请依次输入矩阵非零元的行坐标i、列坐标j、元素值x:
i j v
1 2 12
1 3 9
3 1 -3
3 6 14
4 3 24
5 2 18
6 1 15
6 4 -7
转置后的矩阵:
i j v
1 3 -3
1 6 15
2 1 12
2 5 18
3 1 9
3 4 24
4 6 -7
6 3 14
转置后的矩阵:
i j v
1 3 -3
1 6 15
2 1 12
2 5 18
3 1 9
3 4 24
4 6 -7
6 3 14
Program ended with exit code: 0
*/
I do not production code, I just code porters