C语言实现稀疏矩阵存储和转置

稀疏矩阵存储和转置

稀疏矩阵是矩阵中一种特别的矩阵,主要特点是:非零元素占矩阵所有元素的比例极少。那么,对于这种矩阵的存储,就存在很多很节省空间的方式,核心要点也就是舍弃那些无用元素即零元素,下面将以两种存储方式进行程序设计的实现:

关于稀疏矩阵的COO存储和CSR存储方式,以及不同存储方式的转置矩阵,使用C语言实现逻辑功能,稀疏矩阵二维阵列及行列长度均保存在input.bat文件中,文件见问末,详细代码如下:

使用C语言实现,通过VC++6.0开发工具实现。

// 完整代码
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"


#define MAXSIZE 100       //最大非零元数
//COO格式 
typedef struct Triple {     //三元组
    int i, j;               //行列下标
    float e;             //非零元元素值
}Triple;
typedef struct TSMatrix {       //矩阵
    Triple data[MAXSIZE + 1];   //三元组表
    int mu, nu, tu;             //矩阵的行列数、非零元个数
}TSMatrix;

//CSR格式 
typedef struct Tuple {     //二元组
    int j;               //列下标
    float e;             //非零元元素值
}Tuple;
typedef struct Dista {     //第一个非空字符距离 
    int l;               //长度 
}Dista;
typedef struct CSRstorage {       //矩阵
    Tuple data[MAXSIZE + 1];   //二元组表,替代两个有关系的一维表
    Dista dist[MAXSIZE + 1];   //距离数组 
    int mu, nu, tu;             //矩阵的行列数、非零元个数
}CSRstorage;

void main()
{
    //声明矩阵 
    TSMatrix M,Tr;//COO
    CSRstorage Xs,XsZ;//CSR
    int i,j,t;
    //打印学生学号和姓名
    printf("学号:2019xxx\t姓名:xxx\n"); 
    //***************************************************************************
    //读取bat文件内容,并以COO格式存儲 
    //***************************************************************************
    int m,n;//长度和宽度
    float sp[15][15]; //自定义二维数组大小
    FILE *p1 = fopen("input.bat", "r");  //input.bat文件放在.c文件所在的文件夹中
    if (p1==NULL)  //检测是否成功打开
    {
        printf("Open failed\n");
    }
    //读取数组长度 
    fscanf(p1,"%d",&m);
    fscanf(p1,"%d",&n);
    M.mu = m;
    M.nu = n;
    //二维数读取矩阵值,并以COO格式存储 
    int temp = 0;
    for (i = 0; i<15; i++)
    {
        for (j = 0; j<15; j++)
        {
            fscanf(p1, "%f", &sp[i][j]);   //读入input.bat数据给数组sp
            if(!(sp[i][j]<0.000001&&sp[i][j]>-0.000001))
            {
                M.data[temp].i = i;
                M.data[temp].j = j;
                M.data[temp].e = sp[i][j];
                temp = temp + 1;
            }
        }
    }
    M.tu = temp;
    fclose(p1);//释放指针
    //***************************************************************************
    //打印三个向量,非零
    //***************************************************************************
    printf("COO,打印三个向量如下:\n");
    printf("(%d,%d,%g)\t",M.data[0].i,M.data[0].j,M.data[0].e);
    printf("(%d,%d,%g)\t",M.data[1].i,M.data[1].j,M.data[1].e);
    printf("(%d,%d,%g)\n",M.data[2].i,M.data[2].j,M.data[2].e);
    //***************************************************************************
    //打印原始矩阵 
    //***************************************************************************
    printf("COO,打印原始矩阵如下:\n"); 
    for (i = 0; i<M.mu; i++)
    {
        for (j = 0; j<M.nu; j++)
        {
            int bs = 0;
            for(t = 0;t<M.tu;t++)
            {
                if(i == M.data[t].i && j == M.data[t].j){
                    printf("%g\t",M.data[t].e);
                    bs = 1;
                    break;
                }
            }
            if(bs == 0){
                printf("0\t");
            }
        }
        putchar('\n');//每行结束换行
    }
    //***************************************************************************
    //矩阵转置
    //***************************************************************************
    Tr.mu = M.nu;
    Tr.nu = M.mu;
    Tr.tu = M.tu;
    for(t = 0;t<M.tu;t++)
    {
        Tr.data[t].i = M.data[t].j;
        Tr.data[t].j = M.data[t].i;
        Tr.data[t].e = M.data[t].e;
    }
    //***************************************************************************
    //打印转置矩阵 
    //***************************************************************************
    printf("COO,打印转置矩阵如下:\n");
    for (i = 0; i<Tr.mu; i++)
    {
        for (j = 0; j<Tr.nu; j++)
        {
            int bs = 0;
            for(t = 0;t<Tr.tu;t++)
            {
                if(i == Tr.data[t].i && j == Tr.data[t].j){
                    printf("%g\t",Tr.data[t].e);
                    bs = 1;
                    break;
                }
            }
            if(bs == 0){
                printf("0\t");
            }
        }
        putchar('\n');//每行结束换行
    }
    //***************************************************************************
    //以 CSR格式存儲 Xs
    //***************************************************************************
    Xs.mu = m;
    Xs.nu = n;
    int num = 0;
    for (i = 0; i<m; i++)
    {
        Xs.dist[i].l = num;
        for (j = 0; j<n; j++)
        {
            
            if(!(sp[i][j]<0.000001&&sp[i][j]>-0.000001))
            {
                Xs.data[num].j = j;
                Xs.data[num].e = sp[i][j];
                num = num + 1;
            }
        }
    }
    Xs.dist[m].l = num;
    Xs.tu = num;
    //***************************************************************************
    //打印三個向量 
    //***************************************************************************
    //方式一,先计算出三个,再打印
    //方式二,一直打印,累计三个
    printf("CSR,打印三个向量:\n");
    int js = 0;
    for(i=1;i<=m;i++)
    {
        if(js>=3)
        {
            break;
        }
        for(j=0;j<Xs.dist[i].l-Xs.dist[i-1].l;j++)
        {
            if(js>=3)
            {
                break;
            }
            printf("(%d,%d,%g)\t",Xs.dist[i-1].l,Xs.data[Xs.dist[i-1].l+j].j,Xs.data[Xs.dist[i-1].l+j].e);
            js = js + 1;
        }
    }
    //***************************************************************************
    //打印原始矩陣 
    //***************************************************************************
    printf("\nCSR,打印原始矩阵如下:\n"); 
    for (i = 0; i<Xs.mu; i++)
    {
        if(Xs.dist[i+1].l-Xs.dist[i].l>0)
        {
            for(j = 0; j<Xs.nu; j++)
            {
                int bs = 0;
                for(t = Xs.dist[i].l;t<Xs.dist[i+1].l;t++)
                {
                    if(j == Xs.data[t].j){
                        printf("%g\t",Xs.data[t].e);
                        bs = 1;
                        break;
                    }
                }
                if(bs == 0){
                    printf("0\t");
                }
            } 
        } else {
            for(j = 0; j<Xs.nu; j++)
            {
                printf("0\t");
            }
        }
        putchar('\n');//每行结束换行
    }
    //***************************************************************************
    //矩陣转置 XsZ
    //***************************************************************************
    XsZ.mu = Xs.nu;
    XsZ.nu = Xs.mu;
    XsZ.tu = Xs.tu;
    int Znum = 0;
    for(i=0;i<XsZ.nu;i++)
    {
        XsZ.dist[i].l = Znum;
        for(j=0;j<XsZ.tu;j++)
        {
            if(i == Xs.data[j].j)
            {
                XsZ.data[Znum].e = Xs.data[j].e; 
                for(t=0;t<Xs.mu;t++){
                    if(j>=Xs.dist[t].l&&j<=Xs.dist[t+1].l){
                        XsZ.data[Znum].j = t;
                    }
                }
                Znum = Znum + 1;
            }
        }
    }
    XsZ.dist[XsZ.nu].l = Znum;
    //***************************************************************************
    //打印转置矩阵 
    //***************************************************************************
    printf("CSR,打印转置矩阵如下:\n"); 
    for (i = 0; i<XsZ.mu; i++)
    {
        if(XsZ.dist[i+1].l-XsZ.dist[i].l>0)
        {
            for(j = 0; j<XsZ.nu; j++)
            {
                int bs = 0;
                for(t = XsZ.dist[i].l;t<XsZ.dist[i+1].l;t++)
                {
                    if(j == XsZ.data[t].j){
                        printf("%g\t",XsZ.data[t].e);
                        bs = 1;
                        break;
                    }
                }
                if(bs == 0){
                    printf("0\t");
                }
            } 
        } else {
            for(j = 0; j<Xs.nu; j++)
            {
                printf("0\t");
            }
        }
        putchar('\n');//每行结束换行
    }
    system("pause");//运行结果停留显示,不会一闪而过
}

input.bat文件内容示例如下:
下面展示一些 文本内容。

15
15
0 2.8 0 0 0 0 0 0 0 0 0 0 0 0 0
-4.3 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3
0 0 0 0 0 0 8 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 3.5 0 0 0 86 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 7 0 0 0
0 0 4 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 7 0 0 0 0 0 0 0 0 0 0 5 0 0
0 0 0 3 0 0 23 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 6 0 0 0 0 1.1 0 0 0
9 0 0 0 0 0 0 0 2 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 -8.52
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值