ㅤcoderitl

V1

2022/02/07阅读:88主题:萌绿

C语言-系数矩阵转置

1. 问题描述

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

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

2. 了解什么是稀疏矩阵


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

3. 输入数据样例

第一组数据:
行  列  数据元素值
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

4. 解决方案

#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. 结果输出

分类:

后端

标签:

C++

作者介绍

ㅤcoderitl
V1