三元组法存储稀疏矩阵极其转秩运算

稀疏矩阵:若一个矩阵中,绝大部分数值都为0,或者相等,只有极少数数值非0,那么这种矩阵被称为稀疏矩阵。

衡量一个矩阵是不是稀疏矩阵的一般性原则:稀疏因子:(非0数值个数 / 总个数 * 100%)  <  0.15%

 0123456
00400010
10000900
20208000
30600307
40000000
50000500

从稀疏矩阵的定义看,若使用全存储方案,明显是极其耗费空间的!

在此介绍一种压缩存储方案:三元组法

对于矩阵中的每一个元素,记录其行 ,列和值这三个数据, 称为三元数据;由于稀疏矩阵中存在多个非0元素,那么,这些元素的三元数据集合,称为三元组。

要求三元组中的数据,按行值升序, 行值相同的,按列值升序排列。

三元组下标行值列值
0014
1051
2149
3212
4238
5316
6343
7367
8545

使用一个结构体来控制此三元组:

typedef struct TRIAD {
    int row;
    int col;
    int value;
}

同样使用一个结构体来控制矩阵:

typedef struct MATRIX{
    int count;
    int MaxRow;
    int MaxCol;
    TRIAD *triad;
}MATRIX;

基于三元组的稀疏矩阵的转秩运算,即将上述矩阵转制成:

 012345
0000000
1402600
2000000
3008000
4090305
5100000
6000700

为实现转秩,需进行以下操作:

  1. 申请一个maxCol + 1个元素的数组Index;
  2. 遍历原三元组,以列值+1为Index的下标, 给Index的元素加一
  3. 元素加一000 + 1 + 1 + 100 + 10 + 1 + 1 + 10 + 10 + 1
    Index下标01234567
    下标对应的值00301311

    将上述Index的值递加,得到:

    01234567
    00334789

     

 

 

上述的得到的Index数组的意义还有:未来转秩后的矩阵,下标为Index的那一行的第一个元素在目标三元组中的下标就是Index【index】

这句话该怎么理解呢?就是说将未转秩矩阵的列值做为下表,在Index数组中所对应的值,就是转秩后矩阵Index所对应的下标。

因为在转秩前三元组就是按升序排列的,所以Index数组对应的值必然是那一行的第一个元素,在填入元素后将Index数组的值加一,下次再碰到同一行的元素就会填到该行的第二个元素位置。语言是生硬的,下面给出一个例子,进行一下变量跟踪,立马就会明白!!!

Index数组下标01234567
value00334789
值加一 value + 1   value+ 1  

 

 

 

 

转秩前Index数组下标转秩前三元组转秩后Index数组下标转职后三元组
0(0, 1, 4)0(1,  0,  4)
1(0, 5, 1)1 
2(1, 4 ,9)2 
3(2, 1 ,2)3 
4(2, 3, 8)4 
5(3, 1, 6)5 
6(3, 4, 3)6 
7(3, 6, 7)7(5, 0, 1)
8(5, 4, 5)8 

 

 

 

 

 

 

 

 

 

 

如上两表所示:第一个转秩前三元组的列值为1 , 在Index数组中寻找下标为1的其所对应的值,为0;则表明该三元组转秩后在新的Index数组中位于下标为0的位置,将该三元组行列互换,填入相应的位置,并且给原Index数组下标为1的值加一即可。然后再对第二个三元组进行操作,其列值为5, 在原Index数组中寻找下标为5的其所对应的值,为7; 则表明该三原组转秩后在新的Index数组中位于下标为7的位置,将该三元组行列互换,填入相应位置,且给原Index数组下标为5的值加一。后续以此类推... ...

具体实现代码如下(C):

#include <stdio.h>
#include <malloc.h>

#include "mec.h"
#include "triad.h"
#include "usertype.h"

boolean initMatrix(MATRIX **matrix, TRIAD *triad, int count, int MaxRow, int MaxCol) {
    if(NULL == matrix || NULL != *matrix
        || count <= 0 || MaxRow <= 0 || MaxCol <= 0
        || NULL == triad) {
        return FALSE;
    }

    MATRIX *m = (MATRIX *) calloc(sizeof(MATRIX), 1);
    m->count = count;
    m->MaxRow = MaxRow;
    m->MaxCol = MaxCol;
    m->triad =  (TRIAD *) calloc(sizeof(TRIAD), count);

    int index;
    for(index = 0; index < count; index++) {
        m->triad[index].row = triad[index].row;
        m->triad[index].col = triad[index].col;
        m->triad[index].value = triad[index].value;
    }
    *matrix = m;

    return TRUE;
}

boolean showMatrix(MATRIX *matrix) {
    int i;
    int j;
    int index = 0;

    printf("矩阵如下:\n");
    for(i = 0; i < matrix->MaxRow; i++) {
        for(j = 0; j < matrix->MaxCol; j++) {
            if(i == matrix->triad[index].row && j == matrix->triad[index].col) {
                printf("%4d", matrix->triad[index].value);
                index++;
            } else {
                printf("%4d", 0);
            }
        }
        printf("\n");
    }

    return TRUE;
}

void destoryMatix(MATRIX **matrix) {
    if(NULL == matrix || NULL == *matrix) {
        return;
    }

    free((*matrix)->triad);
    free(*matrix);
    *matrix = NULL;
    printf("销毁成功!!!");
}

void getMatrix(MATRIX **matrix) {
    int MaxRow;
    int MaxCol;
    int count;

    int index;
    int row;
    int col;
    int value;

    printf("请输入最大行列数:\n");
    scanf("%d%d", &MaxRow, &MaxCol);
    printf("请输入有效元素个数:\n");
    scanf("%d", &count);

    TRIAD *triad = (TRIAD *) calloc(sizeof(TRIAD), count);
    printf("请输入有效元素行列及值:\n");
    for(index = 0; index < count; index++) {
        printf("第%d/%d个有效元素", index + 1, count);
        scanf("%d%d%d", &row, &col, &value);
        triad[index].row = row;
        triad[index].col = col;
        triad[index].value = value;
    }

    initMatrix(matrix, triad, count, MaxRow, MaxCol);
    free(triad);
}

MATRIX *revangeMatrix(MATRIX *matrix) {
    MATRIX *result = (MATRIX *) calloc(sizeof(MATRIX), 1);
    result->triad = (TRIAD *) calloc(sizeof(TRIAD), matrix->count);
    result->count = matrix->count;
    result->MaxRow = matrix->MaxCol;
    result->MaxCol = matrix->MaxRow;

    int *index = (int *) calloc(sizeof(TRIAD), (matrix->MaxCol) + 1);
    int i;

    for(i = 0; i < matrix->count; i++) {
        index[matrix->triad[i].col + 1]++;
    }

    for(i = 1; i< matrix->MaxCol + 1; i++) {
        index[i] += index[i - 1];
        printf("%d", index[i]);
    }

    int t;
    TRIAD triad;
    for(i = 0; i < matrix->count; i++) {
        triad = matrix->triad[i];
        t = index[triad.col];
        result->triad[t].row = triad.col;
        result->triad[t].col = triad.row;
        result->triad[t].value = triad.value;
        index[triad.col]++;
    }

    free(index);

    return result;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值