C语言实现-稀疏矩阵转置

问题描述

  输入矩阵的行数、列数和非零元素个数,以及所有非零元素,非零元素包括每个元素的行号、列号、元素值。

  要求:1. 输入的非零元素个数必须满足稀疏矩阵要求,输入过程检测是否满足此要求,若不满足,则重新输入非零元素个数;
        2. 非零元素按行号从小到大顺序输入,相同行号的元素,列号从小到大输入,输入过程检测是否满足此要求,若不满足,则重新输入当前非零元素的行号、列号和元素值
        

了解什么是稀疏矩阵

/**
 * 稀疏矩阵: 是指矩阵中大多数元素为 0 的矩阵。从直观上讲,当非零元素个数低于总元素的 30%
 * 时,这样的矩阵为稀疏矩阵
 *  1. 稀疏矩阵的三元组存储表示
 *      对于稀疏矩阵的存储压缩,采取只存储非零元素的方法。由于稀疏矩阵中非零元素 a_i_j 的分布没有
 *      规律,因此再存储非零元素值的同时,还必须存储该非零元素在矩阵中所处的行号和列号的位置,这就是
 *      稀疏矩阵的三元组表 表示法。
 *
 *  三元组结构:
 *      该非零元素所在的行值       该非零元素所在的列值       该非零元素的值
 *              row                     col                 e
 *
 *   说明: 为处理方便,将稀疏矩阵中非零元素的三元组按照 "行序为主序" 的一维结构体数组进行存放,
 *        将矩阵的每一行(行由小到大)的全部非零元素的三元组按列号递增存放.
 *
 *   矩阵转置:
 *      指变换元素的位置,把位于(row,col) 位置上的元素转换到(col,row)位置上,即把元素的行列互换
 *
 */

输入数据样例

第一组数据:
行 	列 	数据元素值
3 	5 		4
--------------------
1 	1 		1
1 	4 		32
2 	3 		4
3 	2 		15

第二组数据:
行 	列 	数据元素值
3 	5 		4
--------------------
1 	1 		1
1 	4 		32
2 	3 		4
2  	1 		15
3   2       15


第三组数据:
行 	列 	数据元素值
3 	5 		6

非零元素不满足条件重新输入: 4
--------------------
1 	1 		1
1 	4 		32
2 	3 		4
3   2       15

解决方案

#include <stdio.h>

/* 非零元素的个数最多为 255 */
#define MAX_SIZE 255

typedef int ElementType;

typedef struct {
    /* 非零元素的行下标 */
    int row;
    /* 非零元素的列下标 */
    int col;
    /* 该非零元素的值 */
    ElementType e;
} Triple;


typedef struct {
    /* 该非零元素的三元组表 MAX_SIZE+1: 表示 data[0] 为使用 */
    Triple data[MAX_SIZE + 1];
    /* 矩阵的行数 */
    int rows;
    /* 矩阵的列数 */
    int cols;
    /* 矩阵的非零元素个数 */
    int length;
} TSMatrix;




/**
 * 稀疏矩阵列序递增转置算法
 * @param A 原矩阵
 * @param B 转置后
 */
void TransposeTSMatrix(TSMatrix A, TSMatrix *B);

void printT(TSMatrix B);

void InputT(TSMatrix *A);
int main() {
    TSMatrix A, B;
    InputT(&A);

    /* 转置前输出 */
    printf("Before:\n");
    printT(A);

    TransposeTSMatrix(A, &B);

    /* 转置后输出 */
    printf("After:\n");
    printT(B);

    return 0;
}

void TransposeTSMatrix(TSMatrix A, TSMatrix *B) {
    /* 把矩阵 A 转置到 B 所指向的矩阵中去。矩阵用三元组表示 */
    int i, j, k;
    /* B的行 = A 的列 */
    B->rows = A.cols;
    /* B的列 = A的行 */
    B->cols = A.rows;
    /* 矩阵元素个数相同 */
    B->length = A.length;

    /* 如果 B元素个数大于 0 */
    if (B->length > 0) {
        /* j为辅助计数器,记录转置后的三元组在三元组表B中的下标值 */
        j = 1;
        /* 扫描三元组表 A共 A.cols,每次寻找到列值为 k 的三元组进行转置 */
        for (k = 1; k <= A.cols; k++) {
            for (i = 1; i <= A.length; i++) {
                /* 从头到尾扫描三元组表A,寻找 col 值为 k 的三元组进行转置 */
                if (A.data[i].col == k) {
                    B->data[j].row = A.data[i].col;
                    B->data[j].col = A.data[i].row;
                    B->data[j].e = A.data[i].e;
                    /* 计数器 j 加 1,指向本行下一个转置后元素的位置下标 */
                    j++;
                }
            } /* inner for end */
        } /* out for end */
    } /* if end */
} /* TransposeTSMatrix end */


void printT(TSMatrix B) {
    int i, j;
    int t = 1;
    int zero = 0;
    for (i = 1; i <= B.rows; i++) {
        for (j = 1; j <= B.cols; j++) {
            if (B.data[t].row == i && B.data[t].col == j) {
                printf("%-4d", B.data[t].e);
                t++;
            } else printf("%-4d", zero);
        }
        printf("\n");
    }
}

void InputT(TSMatrix *A) {
    int i;
    /*
     * 目标:
     *    存储一个三元组
     *      1. 先满足输入的行列条件
     *      2. 再满足非零元素个数
     *      3. 实现三元组创建
     * */

    /* 第一次输入行列: 获取对应矩阵的行数和列数 */
    scanf("%d%d", &A->rows, &A->cols);

    /* 输入的非零元素个数必须满足稀疏矩阵要求,输入过程检测是否满足此要求,若不满足,则重新输入非零元素个数 */
    do {
        /* 输入非零元素个数 */
        scanf("%d", &A->length);
        /* 如果非零元素个数大于 4,重新输入 => 矩阵大小为 3 行 5 列,6 个非零元素;(6 个非零元素,不是稀疏矩阵,输入错误) */
    } while ((A->length > (A->rows * A->cols * 0.3))); /* 限制非零元素个数的 do...while end  */

    /* 非零元素个数满足后: 输入第一组矩阵表元素 */
    scanf("%d%d%d", &A->data[1].row, &A->data[1].col, &A->data[1].e);

    /**
    *  非零元素按行号从小到大顺序输入,相同行号的元素,列号从小到大输入,输入过程检测是否满足此要求,
    *  若不满足,则重新输入当前非零元素的行号、列号和元素值
    */
    for (i = 2; i <= A->length; i++) {
        do {
            /* 输入三元组表: 获取对应位置下标的值 */
            scanf("%d%d%d", &A->data[i].row, &A->data[i].col, &A->data[i].e);
        } while (A->data[i].row < A->data[i - 1].row ||
                 A->data[i].row == A->data[i - 1].row && A->data[i].col <= A->data[i - 1].col);
    }
}

结果输出

在这里插入图片描述

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值