c语言 三元组存储稀疏矩阵并转置

实验内容:

定义一个 10*10 的稀疏矩阵,试定义一个三元组结构,以行优先的形式存储上述矩阵,并实现:
(1) 上述三元组存储的矩阵的转置
(2) 输出原始 10*10 矩阵及其三元组表示
(3) 输出转置后的 10*10 矩阵及其三元组表示

#include <stdio.h>
#include <string.h>//memset函数必要头文件
#define OK 1
#define MAXSIZE 100     //假设非零元个数的最大值为100
typedef int status;

/*三元组顺序表存储*/
typedef struct {
    int i,j;           //该非零元的行下标和列下标
    int e;            //值
}Triple;
typedef struct {
    Triple data[MAXSIZE+1];       //非零元三元组表,data[0]未用
    int mu,nu,tu;          //矩阵的行数、列数和非零元个数
}TSMatrix;

/*对三元组赋值*/
status Inittsmarix(TSMatrix *M)
{
    M->mu=10;//矩阵基本信息,行列以及非零个数
    M->nu=10;
    M->tu=16;
    int i,j;
    for(i=1;i<=5;i++)//手动输入数据,下同
    {
        M->data[i].i=i;
        M->data[i].j=i;
    }
    M->data[1].e=2;
    M->data[2].e=1;
    M->data[3].e=1;
    M->data[4].e=5;
    M->data[5].e=3;
    M->data[6].i=10;
    M->data[6].j=10;
    M->data[6].e=8;
    M->data[7].i=6;
    M->data[7].j=3;
    M->data[7].e=3;
    M->data[8].i=7;
    M->data[8].j=4;
    M->data[8].e=8;
    M->data[9].i=9;
    M->data[9].j=7;
    M->data[9].e=2;
    M->data[10].i=10;
    M->data[10].j=2;
    M->data[10].e=1;
    M->data[11].i=2;
    M->data[11].j=5;
    M->data[11].e=5;
    M->data[12].i=3;
    M->data[12].j=8;
    M->data[12].e=1;
    M->data[13].i=6;
    M->data[13].j=8;
    M->data[13].e=3;
    return OK;
}

/*转置矩阵*/
status TransposeSMatrix(TSMatrix M,TSMatrix *T){
    //采用三元组表存储表示,求稀疏矩阵M的转置矩阵T
    T->mu = M.nu;//基本信息的复制,行列数值交换
    T->nu = M.mu;
    T->tu = M.tu;
    if(T->tu)//非零元不为零时
    {
        int q = 1;
        int col,p;
        for(col = 1;col <= M.nu; ++col)
        for(p = 1; p <= M.tu; ++p)
        if(M.data[p].j == col)
        {
            T->data[q].i = M.data[p].j;//转置本质是行以及列的交换
            T->data[q].j = M.data[p].i;
            T->data[q].e = M.data[p].e;
            ++q;
        }
    }
    return OK;
}

int main()
{
    TSMatrix M,T;
    int i,j;
    int matris[10][10];//生成一个二维数组便于矩阵具象化
    memset(matris,0,sizeof(matris));//对数组元素全部初始化为0
    Inittsmarix(&M);//初始化三元组

    for(i=1;i<14;i++)
        matris[M.data[i].i-1][M.data[i].j-1]=M.data[i].e;//把三元组信息传入数组
    printf("Before:\n");

    for(j=0;j<10;j++)
    {
        for(i=0;i<10;i++)//用两个循环遍历二维数组
        printf("%d ",matris[j][i]);//打印数组元素
        printf("\n");
    }
    for(i=1;i<14;i++)
        printf("%d %d %d\n",M.data[i].i,M.data[i].j,M.data[i].e);

    TransposeSMatrix(M,&T);//转置三元组
    printf("\n");
    printf("later:\n");

    memset(matris,0,sizeof(matris));//把二维数组重置为0
    
    for(i=1;i<14;i++)
        matris[T.data[i].i-1][T.data[i].j-1]=T.data[i].e;
    for(j=0;j<10;j++)
    {
        for(i=0;i<10;i++)
        printf("%d ",matris[j][i]);//打印转置后的稀疏矩阵
        printf("\n");
    }
    for(i=1;i<14;i++)
        printf("%d %d %d\n",T.data[i].i,T.data[i].j,T.data[i].e);
}

代码中用的是转置算法,下面附上快速转置的伪代码:

     /*快速转置*/
status FastTransposeSMatrix(TSMatrix M, TSMatrix *T){
    //采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵T
    int col,t,p;
    T->mu = M.nu;
    T->nu = M.mu;
    T->tu = M.tu;
    if(T->tu)
    {
        for(col = 1;col <= M.nu; ++col)
        num[col]=0;
        for(t = 1; t <= M.tu; ++t)
        ++num[M.data[t].j];
        cpot[1]=1;
        //求第col列中第一个非零元在b.data中的序号
        for(col=2;col<=M.nu;++col)
        cpot=[col]=cpot[col-1]+num[col-1];
        for(p=1;p<=M.tu;++p)
        {
            col=M.data[p].j;
            q=cpot[col];
            T->data[q].i=M.data[p].j;
            T->data[q].j=M.data[p].i;
            T->data[q].e=M.data[p].e;
            ++cpot[col];
        }//for
    }//if
    return OK;
}

方法一:快速转置 快速转置的思路是,不用创建一个新的数组存储转置后的矩阵,而是直接在原矩阵上进行操作,将每个非零元素的行列坐标互换即可。 具体实现步骤如下: 1. 定义一个临时变量 temp 用于交换两个元素的行列坐标。 2. 遍历原矩阵的所有非零元素,将它的行列坐标互换。 3. 由于原矩阵已经被修改,所以再次遍历原矩阵时,需要按列优先的方式遍历,即先遍历第一列的所有元素,然后是第二列的所有元素,以此类推。 4. 将转置后的矩阵输出。 代码实现如下: ```c #include <stdio.h> #define MaxSize 100 typedef struct { int i, j, e; } Triple; typedef struct { Triple data[MaxSize + 1]; int m, n, len; } TSMatrix; void TransposeTSMatrix(TSMatrix M, TSMatrix *T) { int col, t, p; T->m = M.n; T->n = M.m; T->len = M.len; if (T->len > 0) { p = 1; for (col = 1; col <= M.n; col++) { for (t = 1; t <= M.len; t++) { if (M.data[t].j == col) { T->data[p].i = M.data[t].j; T->data[p].j = M.data[t].i; T->data[p].e = M.data[t].e; p++; } } } } } int main() { int m, n, k, i, j, e; TSMatrix M, T; printf("请输入矩阵的行数、列数和非零元素个数:\n"); scanf("%d%d%d", &m, &n, &k); M.m = m; M.n = n; M.len = k; printf("请输入矩阵三元组表示:\n"); for (i = 1; i <= k; i++) { scanf("%d%d%d", &M.data[i].i, &M.data[i].j, &M.data[i].e); } TransposeTSMatrix(M, &T); printf("转置后的矩阵三元组表示为:\n"); for (i = 1; i <= T.len; i++) { printf("%d %d %d\n", T.data[i].i, T.data[i].j, T.data[i].e); } return 0; } ``` 方法二:行逻辑链接转置法 行逻辑链接转置法是指,首先创建一个新的数组存储转置后的矩阵,然后通过行逻辑链接的方式将原矩阵中每一列的非零元素存储到新矩阵的相应行上。 具体实现步骤如下: 1. 定义一个新的数组 B 来存储转置后的矩阵。 2. 遍历原矩阵的每一列,将每一列的非零元素存储到新矩阵的相应行上。 3. 计算每一行的非零元素个数。 4. 计算每一行的第一个非零元素在 B 数组中的位置。 5. 将转置后的矩阵输出。 代码实现如下: ```c #include <stdio.h> #include <stdlib.h> #define MaxSize 100 typedef struct { int i, j, e; } Triple; typedef struct { Triple data[MaxSize + 1]; int rpos[MaxSize + 1]; int m, n, len; } RLSMatrix; void TransposeRLSMatrix(RLSMatrix M, RLSMatrix *T) { int i, j, k, p; T->m = M.n; T->n = M.m; T->len = M.len; if (T->len > 0) { p = 1; for (i = 1; i <= M.n; i++) { T->rpos[i] = p; } for (i = 1; i <= M.m; i++) { for (k = M.rpos[i]; k < M.rpos[i + 1]; k++) { j = M.data[k].j; T->data[p].i = j; T->data[p].j = i; T->data[p].e = M.data[k].e; p++; } } } } int main() { int m, n, k, i, j, e; RLSMatrix M, T; printf("请输入矩阵的行数、列数和非零元素个数:\n"); scanf("%d%d%d", &m, &n, &k); M.m = m; M.n = n; M.len = k; printf("请输入矩阵三元组表示:\n"); for (i = 1; i <= k; i++) { scanf("%d%d%d", &M.data[i].i, &M.data[i].j, &M.data[i].e); } M.rpos[m + 1] = k + 1; for (i = m; i >= 1; i--) { M.rpos[i] = M.rpos[i + 1]; while (M.data[M.rpos[i] - 1].i == i) { M.rpos[i]--; } } TransposeRLSMatrix(M, &T); printf("转置后的矩阵三元组表示为:\n"); for (i = 1; i <= T.len; i++) { printf("%d %d %d\n", T.data[i].i, T.data[i].j, T.data[i].e); } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值