Sparse Matrix - triplet sequence table

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

Guess you like

Origin www.cnblogs.com/zhulmz/p/11754638.html