数据结构实践——稀疏矩阵相加

简介: 本文针对数据结构基础系列网络课程(5):数组与广义表的实践项目。【项目 - 稀疏矩阵相加】   采用三元组存储稀疏矩阵,设计两个稀疏矩阵相加的运算算法 提示1:两个行数、列数相同的矩阵可以相加 提示2:充分利用已经建立好的算法库解决问题[参考解答1](程序中使用的头文件”tup.h”见稀疏矩阵的三元组表示算法库) #include <stdio.

本文针对数据结构基础系列网络课程(5):数组与广义表的实践项目。

【项目 - 稀疏矩阵相加】
  采用三元组存储稀疏矩阵,设计两个稀疏矩阵相加的运算算法
提示1:两个行数、列数相同的矩阵可以相加
提示2:充分利用已经建立好的算法库解决问题

[参考解答1](程序中使用的头文件”tup.h”见稀疏矩阵的三元组表示算法库) 

#include <stdio.h>
#include "tup.h"
bool MatAdd(TSMatrix a,TSMatrix b,TSMatrix &c)
{
    int i,j;
    ElemType va,vb,vc;
    if (a.rows!=b.rows || a.cols!=b.cols)
        return false;                        //行数或列数不等时不能进行相加运算
    c.rows=a.rows;
    c.cols=a.cols;       //c的行列数与a的相同
    c.nums=0;
    for(i=0; i<M; i++)
        for(j=0; j<N; j++)
        {
            Assign(a,va,i,j);
            Assign(b,vb,i,j);
            vc=va+vb;
            if(vc)
                Value(c,vc,i,j);
        }
    return true;
}

int main()
{
    TSMatrix ta,tb,tc;
    int A[M][N]=
    {
        {0,0,1,0,0,0,0},
        {0,2,0,0,0,0,0},
        {3,0,0,0,0,0,0},
        {0,0,0,5,0,0,0},
        {0,0,0,0,6,0,0},
        {0,0,0,0,0,7,4}
    };
    int B[M][N]=
    {
        {0,0,10,0,0,0,0},
        {0,0,0,20,0,0,0},
        {0,0,0,0,0,0,0},
        {0,0,0,50,0,0,0},
        {0,0,20,0,0,0,0},
        {0,0,0,10,0,0,4}
    };
    CreatMat(ta,A);
    CreatMat(tb,B);
    printf("A:\n");
    DispMat(ta);
    printf("B:\n");
    DispMat(tb);
    if(MatAdd(ta, tb, tc))
    {
        printf("A+B:\n");
        DispMat(tc);
    }
    else
    {
        printf("相加失败\n");
    }
    return 0;
}

[参考解答2]
  下面给出的解答,没有利用算法库中已经实现的Assign和Value两个基本运算,而是直接e采取了更为直接的方法去完成。用i和j两个变量扫描三元组a和b,按行序优先的原则进行处理,将结果存放于c中。当a的当前元素和b的当前元素的行号和列号均相等时,将它们的值相加,只有在相加值不为0时,才在c中添加一个新的元素。

#include <stdio.h>
#include "tup.h"
bool MatAdd(TSMatrix a,TSMatrix b,TSMatrix &c)
{
    int i=0,j=0,k=0;
    ElemType v;
    if (a.rows!=b.rows || a.cols!=b.cols)
        return 0;        //行数或列数不等时不能进行相加运算
    c.rows=a.rows;
    c.cols=a.cols;       //c的行列数与a的相同
    while (i<a.nums && j<b.nums)         //处理a和b中的每个元素
    {
        if (a.data[i].r==b.data[j].r)    //行号相等时
        {
            if(a.data[i].c<b.data[j].c)  //a元素的列号小于b元素的列号
            {
                c.data[k].r=a.data[i].r;//将a元素添加到c中
                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元素的列号
            {
                c.data[k].r=b.data[j].r;      //将b元素添加到c中
                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元素的行号
        {
            c.data[k].r=a.data[i].r;      //将a元素添加到c中
            c.data[k].c=a.data[i].c;
            c.data[k].d=a.data[i].d;
            k++;
            i++;
        }
        else                              //a元素的行号大于b元素的行号
        {
            c.data[k].r=b.data[j].r;      //将b元素添加到c中
            c.data[k].c=b.data[j].c;
            c.data[k].d=b.data[j].d;
            k++;
            j++;
        }
    }
    while (i<a.nums)         //a中尚有元素时
    {
        c.data[k].r=a.data[i].r;//将a元素添加到c中
        c.data[k].c=a.data[i].c;
        c.data[k].d=a.data[i].d;
        k++;
        i++;
    }
    while (j<b.nums)         //b中尚有元素时
    {
        c.data[k].r=b.data[j].r;      //将b元素添加到c中
        c.data[k].c=b.data[j].c;
        c.data[k].d=b.data[j].d;
        k++;
        j++;
    }
    c.nums=k;
    return true;
}

int main()
{
    TSMatrix ta,tb,tc;
    int A[M][N]=
    {
        {0,1,0,0,0,0,0},
        {0,2,0,0,0,0,0},
        {3,0,0,0,0,0,0},
        {0,0,0,5,0,0,0},
        {0,0,0,0,6,0,0},
        {0,0,0,0,0,7,4}
    };
    int B[M][N]=
    {
        {0,0,10,0,0,0,0},
        {0,0,0,20,0,0,0},
        {0,0,0,0,0,0,0},
        {0,0,0,50,0,0,0},
        {0,0,20,0,0,0,0},
        {0,0,0,10,0,0,4}
    };
    CreatMat(ta,A);
    CreatMat(tb,B);
    printf("A:\n");
    DispMat(ta);
    printf("B:\n");
    DispMat(tb);
    if(MatAdd(ta, tb, tc))
    {
        printf("A+B:\n");
        DispMat(tc);
    }
    else
    {
        printf("相加失败\n");
    }
    return 0;
}

  对比两种方案,“参考解答1”利用Assign和Value两个基本运算的方案,可以在只知道“矩阵加法是对应位置的元素相加”的基础上就可以求解;而“参考解答2”则不得不关注在数据存储层面的细节,以致于矩阵加法的规则都不容易看出来了。“参考解答2”中繁杂的代码,违反了程序设计中诸多的原则(例如模块化),相对“参考解答1”的简洁中透出的优雅,该不是学习者效仿的思维。

附:1楼评论中带bug的解答,原参考解答2。重点观察少了while (i<a.nums)while (j<b.nums)两个循环,当a和b的最后一个元素不在同一行同一列时,会丢数据的。这个bug的漏网,和main函数中采用的测试数据不够好有关,让两个矩阵非0元素在同一行同一列,忽略了“边界”数据的重要性。
  与此同时,再次体会参考解答1的好处,缺少了一层抽象,对应的就是处处要考虑细节。智者千虑,必有一失,还是要运用上工程中的原则为好。

#include <stdio.h>
#include "tup.h"
bool MatAdd(TSMatrix a,TSMatrix b,TSMatrix &c)
{
    int i=0,j=0,k=0;
    ElemType v;
    if (a.rows!=b.rows || a.cols!=b.cols)
        return 0;        //行数或列数不等时不能进行相加运算
    c.rows=a.rows;
    c.cols=a.cols;       //c的行列数与a的相同
    while (i<a.nums && j<b.nums)         //处理a和b中的每个元素
    {
        if (a.data[i].r==b.data[j].r)    //行号相等时
        {
            if(a.data[i].c<b.data[j].c)  //a元素的列号小于b元素的列号
            {
                c.data[k].r=a.data[i].r;//将a元素添加到c中
                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元素的列号
            {
                c.data[k].r=b.data[j].r;      //将b元素添加到c中
                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元素的行号
        {
            c.data[k].r=a.data[i].r;      //将a元素添加到c中
            c.data[k].c=a.data[i].c;
            c.data[k].d=a.data[i].d;
            k++;
            i++;
        }
        else                              //a元素的行号大于b元素的行号
        {
            c.data[k].r=b.data[j].r;      //将b元素添加到c中
            c.data[k].c=b.data[j].c;
            c.data[k].d=b.data[j].d;
            k++;
            j++;
        }
        c.nums=k;
    }
    return true;
}

int main()
{
    TSMatrix ta,tb,tc;
    int A[M][N]=
    {
        {0,0,1,0,0,0,0},
        {0,2,0,0,0,0,0},
        {3,0,0,0,0,0,0},
        {0,0,0,5,0,0,0},
        {0,0,0,0,6,0,0},
        {0,0,0,0,0,7,4}
    };
    int B[M][N]=
    {
        {0,0,10,0,0,0,0},
        {0,0,0,20,0,0,0},
        {0,0,0,0,0,0,0},
        {0,0,0,50,0,0,0},
        {0,0,20,0,0,0,0},
        {0,0,0,10,0,0,4}
    };
    CreatMat(ta,A);
    CreatMat(tb,B);
    printf("A:\n");
    DispMat(ta);
    printf("B:\n");
    DispMat(tb);
    if(MatAdd(ta, tb, tc))
    {
        printf("A+B:\n");
        DispMat(tc);
    }
    else
    {
        printf("相加失败\n");
    }
    return 0;
}
目录
相关文章
|
5月前
|
存储 算法 编译器
【数据结构原理】稀疏矩阵 - THE SPARSE MATRIX
【数据结构原理】稀疏矩阵 - THE SPARSE MATRIX
71 0
|
6月前
|
存储 人工智能 自然语言处理
什么是数据结构中的特殊矩阵和稀疏矩阵
什么是数据结构中的特殊矩阵和稀疏矩阵
113 0
|
5月前
|
存储 算法 编译器
【霍洛维兹数据结构】数组和结构 | ARRAYS AND STRUCTURES | THE SPARSE MATRIX 稀疏矩阵
【霍洛维兹数据结构】数组和结构 | ARRAYS AND STRUCTURES | THE SPARSE MATRIX 稀疏矩阵
45 0
|
20天前
|
存储 算法 C语言
【C/C++ 数据结构 树】探索C/C++中的二叉树:从理论到实践
【C/C++ 数据结构 树】探索C/C++中的二叉树:从理论到实践
60 0
|
26天前
|
Web App开发 存储 网络协议
C/C++ 数据结构设计与应用(四):C++数据压缩与传输:从理论到实践的全景解析
C/C++ 数据结构设计与应用(四):C++数据压缩与传输:从理论到实践的全景解析
49 3
|
26天前
|
存储 数据处理 C++
C/C++ 数据结构设计与应用(三):运算符重载的策略与实践 (Operator Overloading Strategies and Practices)
C/C++ 数据结构设计与应用(三):运算符重载的策略与实践 (Operator Overloading Strategies and Practices)
20 0
|
2月前
|
缓存 Rust 算法
Rust中的数据结构与算法优化实践
在Rust编程语言中,优化数据结构与算法是提高程序性能的关键。本文首先介绍了Rust的特点,然后重点讨论了如何在Rust中优化数据结构和算法,包括使用标准库中的高效数据结构、自定义数据结构的优化技巧、算法选择与改进、以及Rust特性如所有权和借用检查器的应用。通过实际案例,我们将展示如何在Rust中实现更高效的数据结构与算法。
|
3月前
|
存储 算法
【数据结构】稀疏矩阵和队列
【数据结构】稀疏矩阵和队列
48 0
|
4月前
|
Java 数据库连接 微服务
Java程序员必学知识:高并发+微服务+数据结构+Mybatis实战实践
BATJ最全架构技术合集:高并发+微服务+数据结构+SpringBoot 关于一线互联网大厂网站的一些特点:用户多,分布广泛、大流量,高并发、海量数据,服务高可用、安全环境恶劣,易受网络攻击、功能多,变更快,频繁发布、从小到大,渐进发展、以用户为中心。 如果你工作中够仔细,你会发现这些特点跟高并发、分布式、微服务、Nginx这些技术密切相关的,是因为只要你的公司在上升,用户量级都会与日俱增,高性能、高并发的问题自然避免不了,话不多说往下看。
|
4月前
|
存储 C语言
【数据结构实践课设】新生报道注册管理信息系统
【数据结构实践课设】新生报道注册管理信息系统
22 0