DS-009 37 数据结构:矩阵的压缩存储

Data Structure:Matrix Compression Storage


1 Introduction

In data structures, a compressed storage structure for some specific matrices is provided.

The special matrix we mentioned can be generally divided into the following two types:

  • A matrix containing a large number of identical data elements, such as a symmetric matrix;
  • Matrix containing a large number of 0, such as sparse matrix, upper or lower triangular matrix;

For the two types of matrices above, the compressed storage idea of the data structure is: only one of the same data elements (including element 0) in the matrix is stored.

2 Storage of symmetric matrix and upper/lower triangular matrix

With the idea of data structure compression storage, we can use one dimensional array to store symmetric matrix. Since the data on both sides of the diagonal in the matrix are equal, we only need to store one side of the diagonal (including the diagonal) in the array.

For example, to store the elements in the lower triangle of symmetric matrix, we need to substitute the row number i and column number j of each element into the following formula (i,j≥1):
在这里插入图片描述
If we need to store the elements in the upper triangle, the formula should be:
在这里插入图片描述
An example:
在这里插入图片描述
The matrix above will be stored as:
在这里插入图片描述

3 Storage of sparse matrix

The method of compressing and storing the sparse matrix is to store the non-zero elements in the matrix only. Unlike the previous storage method, the storage of the non-zero elements of the sparse matrix needs to store the row and column labels in the matrix in which the element is located. Also we need to store the size of matrix.

Here are three ways to store a sparse matrix:

  • Triple sequence table
  • Logical-linked sequence table
  • Cross link list

3.1 Triple sequence table

First we will construct the basic structure:

// Structure of triad
typedef struct{
	int i,j;		// Index number
	int data;		// value
}triple;

// Structure of matrix
typedef struct{
	triple data[number];	// Store all the non-zero triple
	int n,m,num;			// n*m: size of the matrix, num: number of non-zero elements
}TSMatrix;

Then try the output:

void display(TSMatrix M){
    for(int i=1;i<=M.n;i++){
        for(int j=1;j<=M.m;j++){
            int value =0;
            for(int k=0;k<M.num;k++){
                if(i == M.data[k].i && j == M.data[k].j){
                    printf("%d ",M.data[k].data);
                    value =1;
                    break;
                }
            }
            if(value == 0)
                printf("0 ");
        }
        printf("\n");
    }
}

int main() {
    TSMatrix M;
    // Initialize the matrix
    M.m=3;
    M.n=3;
    M.num=3;
    
    // All the non-zero elements here
    M.data[0].i=1;
    M.data[0].j=1;
    M.data[0].data=1;
    M.data[1].i=2;
    M.data[1].j=3;
    M.data[1].data=5;
    M.data[2].i=3;
    M.data[2].j=1;
    M.data[2].data=3;
    display(M);
    return 0;
}

Output:
在这里插入图片描述

3.2 Logical-linked sequence table

This storage method is similar with triple sequence table but it improve the efficiency of extracting data.
This method also record the first non-zero element in each row.
在这里插入图片描述
Storage:
在这里插入图片描述
在这里插入图片描述
Code implementation:

/* Sparse matrix storage(Logical-linked sequence table) */
#include <stdio.h>
#define MAXSIZE 12500
#define MAXRC 100
#define ElemType int
typedef struct
{
    int i,j;
    ElemType e;
}Triple;
typedef struct
{
    Triple  data[MAXSIZE+1];
    int rpos[MAXRC+1];	// First position of non-zero elements in every row
    int mu,nu,tu;		// row,column,number of elements
}RLSMatrix;

void display(RLSMatrix M){
    for(int i=1;i<=M.mu;i++){
        for(int j=1;j<=M.nu;j++){
            int value=0;
            if(i+1 <=M.mu){
                for(int k=M.rpos[i];k<M.rpos[i+1];k++){
                    if(i == M.data[k].i && j == M.data[k].j){
                        printf("%d ",M.data[k].e);
                        value=1;
                        break;
                    }
                }
                if(value==0){
                        printf("0 ");
                    }
            }else{
                for(int k=M.rpos[i];k<=M.tu;k++){
                    if(i == M.data[k].i && j == M.data[k].j){
                        printf("%d ",M.data[k].e);
                        value=1;
                        break;
                    }
                }
                if(value==0){
                    printf("0 ");
                }
            }
        }
        printf("\n");
    }
}
int main(int argc, char* argv[])
{
    RLSMatrix M;
    M.tu = 4;
    M.mu = 3;
    M.nu = 4;
    M.rpos[1] = 1;
    M.rpos[2] = 3;
    M.rpos[3] = 4;
    M.data[1].e = 3;
    M.data[1].i = 1;
    M.data[1].j = 2;
    M.data[2].e = 5;
    M.data[2].i = 1;
    M.data[2].j = 4;
    M.data[3].e = 1;
    M.data[3].i = 2;
    M.data[3].j = 3;
    M.data[4].e = 2;
    M.data[4].i = 3;
    M.data[4].j = 1;
    display(M);
    return 0;
}

Output:
在这里插入图片描述

3.3 Cross link list

If we want to add or delete non-zero elements, the two storage methods above will not be suitable, so we introduce a new idea: Cross link list. It combines link list and array:
在这里插入图片描述
Code implementation:

/* Sparse matrix storage(Cross link list) */
#include<stdio.h>
#include<stdlib.h>

typedef struct OLNode
{
    int i,j,e;                      // i:row;j:column;e:value
    struct OLNode *right,*down;     // right pointer and down pointer
}OLNode,*OLink;

typedef struct
{
    OLink *rhead,*chead;            // Head pointer for row and column
    int mu,nu,tu;                   // Size of matrix and the number of non-zero elements
}CrossList;

CrossList CreateMatrix_OL(CrossList M)
{
    int m,n,t;
    int i,j,e;
    OLNode *p,*q;
    printf("Row column and non-zero elements:");
    scanf("%d %d %d",&m,&n,&t);
    M.mu=m;
    M.nu=n;
    M.tu=t;
    if(!(M.rhead=(OLink*)malloc((m+1)*sizeof(OLink)))||!(M.chead=(OLink*)malloc((n+1)*sizeof(OLink))))
    {
        printf("Failed to initalize the matrix");
        exit(0);
    }
    for(i=1;i<=m;i++)
    {
        M.rhead[i]=NULL;
    }
    for(j=1;j<=n;j++)
    {
        M.chead[j]=NULL;
    }
    for(scanf("%d %d %d",&i,&j,&e);0!=i;scanf("%d %d %d",&i,&j,&e))    {
        if(!(p=(OLNode*)malloc(sizeof(OLNode))))
        {
            printf("Failed to initalize the triple");
            exit(0);
        }
        p->i=i;
        p->j=j;
        p->e=e;
        // Link to row
        if(NULL==M.rhead[i]||M.rhead[i]->j>j)
        {
            p->right=M.rhead[i];
            M.rhead[i]=p;
        }
        else
        {
            for(q=M.rhead[i];(q->right)&&q->right->j<j;q=q->right);
            p->right=q->right;
            q->right=p;
        }
        // link to column
        if(NULL==M.chead[j]||M.chead[j]->i>i)
        {
            p->down=M.chead[j];
            M.chead[j]=p;
        }
        else
        {
            for (q=M.chead[j];(q->down)&& q->down->i<i;q=q->down);
            p->down=q->down;
            q->down=p;
        }
    }
    return M;
}
void display(CrossList M){
    for (int i=1;i<=M.nu;i++)
    {
        if (NULL!=M.chead[i])
        {
           OLink p=M.chead[i];
            while (NULL!=p)
            {
                printf("Col:%d\tRolL%d\tVal:%d\n",p->i,p->j,p->e);
                p=p->down;
            }
        }
    }
}
int main()
{
    CrossList M,N;
    M=CreateMatrix_OL(M);
    printf("M:\n");
    display(M);
    return 0;
}

Output:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Tinky2013/article/details/87734892
37
今日推荐