实现稀疏矩阵(采用三元组表示)的基本运算

/**
*    实验题目:
*        实现稀疏矩阵(采用三元组表示)的基本运算
*    实验目的:
*        领会稀疏矩阵三元组的存储结构及其基本算法设计
*    实验内容:
*        假设n x n的稀疏矩阵A采用三元组表示,设计一个程序,实现如下功能:
*    1、生成如下两个稀疏矩阵的三元组a和b。
*       1 0 3 0          3 0 0 0
*       0 1 0 0          0 4 0 0
*       0 0 1 0          0 0 1 0
*       0 0 1 1          0 0 0 2
*    2、输出a转置矩阵的三元组
*    3、输出a+b的三元组
*    4、输出axb的三元组
*/

#include
#include

#define N 4
#define MAX_SIZE 100 // 矩阵中非零元素最多个数

typedef int ElemType;

typedef struct
{
    int r; // 行号
    int c; // 列号
    ElemType d; // 元素值
}TupNode; // 三元组定义

typedef struct
{
    int rows; // 行数值
    int cols; // 列数值
    int nums; // 非零元素个数
    TupNode data[MAX_SIZE];
}TSMatrix; // 三元组顺序表定义

/*------------------------产生稀疏矩阵A的三元组表示t----------------------*/
static void create_matrix(TSMatrix &t, ElemType A[N][N])
{
    int i, j;

    t.rows = N; // 行数值
    t.cols = N; // 列数值
    t.nums = 0; // 非零元素个数
    for(i = 0; i < N; i++)
    {
        for(j = 0; j < N; j++)
        {
            if(A[i][j] != 0)
            {
                t.data[t.nums].r = i; // 行号
                t.data[t.nums].c = j; // 列号
                t.data[t.nums].d = A[i][j]; // 元素值
                t.nums++; // 非零元素个数增1
            }
        }
    }
}

/*------------------------输出三元组表示t----------------------*/
static void disp_matrix(TSMatrix t)
{
    int i;

    if(t.nums <= 0)
        return;
    printf("\t%d\t%d\t%d\n", t.rows, t.cols, t.nums);
    printf("\t------------------\n");
    for(i = 0; i < t.nums; i++)
        printf("\t%d\t%d\t%d\n", t.data[i].r, t.data[i].c, t.data[i].d);
}

/*------------------------求三元组表示t的转置矩阵tb----------------------*/
/**
*   转置矩阵:
*       把矩阵A的行换成相应的列,得到的新矩阵称为A的转置矩阵。
*/
static void tran_matrix(TSMatrix t, TSMatrix &tb)
{
    int p, v;
    int q = 0; // q为tb.data的下标

    tb.rows = t.cols; // 转置矩阵行数值
    tb.cols = t.rows; // 转置矩阵列数值
    tb.nums = t.nums; // 转置矩阵非零元素个数
    if(t.nums != 0)
    {
        for(v = 0; v < t.cols; v++) // tb.data[q]中的记录以c域的次序排列
        {
            for(p = 0; p < t.nums; p++) // p为t.data的下标
            {
                if(t.data[p].c == v)
                {
                    tb.data[q].r = t.data[p].c; // 转置矩阵的行号
                    tb.data[q].c = t.data[p].r; // 转置矩阵的列号
                    tb.data[q].d = t.data[p].d; // 转置矩阵的元素值
                    q++;
                }
            }
        }
    }
}

/*------------------------求c=a+b----------------------*/
static bool matrix_add(TSMatrix a, TSMatrix b, TSMatrix &c) // 引用类型形参c
{
    int i = 0; // a中非零元素个数索引
    int j = 0; // b中非零元素个数索引
    int k = 0; // c中非零元素个数
    ElemType v;

    if(a.rows != b.rows || a.cols != b.cols) // 行数或列数不等时不能进行相加运算
        return false;
    // c的行列数与a的相同
    c.rows = a.rows;
    c.cols = a.cols;
    while(i < a.nums && j < b.nums) // 处理a和b中的元素(假设 a.nums = 6, b.nums = 4)
    {
        if(a.data[i].r == b.data[j].r) // a元素的行号等于b元素的行号
        {
            if(a.data[i].c < b.data[j].c) // a元素的列号小于b元素的列号
            {
                // 将a元素添加到c中
                c.data[k].r = a.data[i].r;
                c.data[k].c = a.data[i].c;
                c.data[k].d = a.data[i].d;
                k++;
                i++;
            }
            else if(a.data[i].c > b.data[j].c) // a元素的列号大于b元素的列号
            {
                // 将b元素添加到c中
                c.data[k].r = b.data[j].r;
                c.data[k].c = b.data[j].c;
                c.data[k].d = b.data[j].d;
                k++;
                j++;
            }
            else // a元素的列号等于b元素的列号
            {
                v = a.data[i].d + b.data[j].d;
                if(v != 0) // 只将不为0的结果添加到c中
                {
                    c.data[k].r = a.data[i].r;
                    c.data[k].c = a.data[i].c;
                    c.data[k].d = v;
                    k++;
                }
                i++;
                j++;
            }
        }
        else if(a.data[i].r < b.data[j].r) // a元素的行号小于b元素的行号
        {
            // 将a元素添加到c中
            c.data[k].r = a.data[i].r;
            c.data[k].c = a.data[i].c;
            c.data[k].d = a.data[i].d;
            k++;
            i++;
        }
        else // a元素的行号大于b元素的行号
        {
            // 将b元素添加到c中
            c.data[k].r = b.data[j].r;
            c.data[k].c = b.data[j].c;
            c.data[k].d = b.data[j].d;
            k++;
            j++;
        }
        c.nums = k;
    }

    return true;
}

/*------------------------返回三元组t表示的A[i][j]值----------------------*/
static int get_value(TSMatrix t, int i, int j)
{
    int k = 0;

    while(k < t.nums && (t.data[k].r != i || t.data[k].c != j))
        k++;
    if(k < t.nums)
        return t.data[k].d;
    else
        return 0;
}

/*------------------------求c=a*b----------------------*/
static bool matrix_mul(TSMatrix a, TSMatrix b, TSMatrix &c) // 引用类型形参c
{
    int i;
    int j;
    int k;
    int p = 0; // 矩阵c的非零元素个数
    ElemType s;

    if(a.cols != b.rows) // a的列数不等于b的行数时不能进行乘法运算
        return false;
    for(i = 0; i < a.rows; i++) // 矩阵c的行数
    {
        for(j = 0; j < b.cols; j++) // 矩阵c的列数
        {
            s = 0;
            for(k = 0; k < a.cols; k++)
            {
                 s = s + get_value(a, i, k) * get_value(b, k, j); // 求三元组元素
            }
            if(s != 0) // 产生一个三元组元素
            {
                c.data[p].r = i; // 三元组元素的行号
                c.data[p].c = j; // 三元组元素的列号
                c.data[p].d = s; // 三元组元素的元素值
                p++;
            }
        }
    }

    c.rows = a.rows;
    c.cols = b.cols;
    c.nums = p; // 矩阵c的非零元素个数

    return true;
}

int main(void)
{
    ElemType a1[N][N] = {
        {1, 0, 3, 0},
        {0, 1, 0, 0},
        {0, 0, 1, 0},
        {0, 0, 1, 1}
    };
    ElemType b1[N][N] = {
        {3, 0, 0, 0},
        {0, 4, 0, 0},
        {0, 0, 1, 0},
        {0, 0, 0, 2}
    };

    TSMatrix a, b, c;

    create_matrix(a, a1);
    create_matrix(b, b1);
    printf("a的三元组:\n");
    disp_matrix(a);
    printf("b的三元组:\n");
    disp_matrix(b);
    printf("a转置为c\n");
    tran_matrix(a, c);
    printf("c的三元组:\n");
    disp_matrix(c);

    printf("c=a+b\n");
    matrix_add(a, b, c);
    printf("c的三元组:\n");
    disp_matrix(c);

    printf("c=a*b\n");
    matrix_mul(a, b, c);
    printf("c的三元组:\n");
    disp_matrix(c);

    return 0;
}
测试结果:

a的三元组:
        4       4       6
        ------------------
        0       0       1
        0       2       3
        1       1       1
        2       2       1
        3       2       1
        3       3       1
b的三元组:
        4       4       4
        ------------------
        0       0       3
        1       1       4
        2       2       1
        3       3       2
a转置为c
c的三元组:
        4       4       6
        ------------------
        0       0       1
        1       1       1
        2       0       3
        2       2       1
        2       3       1
        3       3       1
c=a+b
c的三元组:
        4       4       6
        ------------------
        0       0       4
        0       2       3
        1       1       5
        2       2       2
        3       2       1
        3       3       3
c=a*b
c的三元组:
        4       4       6
        ------------------
        0       0       3
        0       2       3
        1       1       4
        2       2       1
        3       2       1
        3       3       2

你可能感兴趣的:(数据结构与算法)