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

本文探讨了数据结构基础网络课程中的稀疏矩阵相加项目,介绍了如何采用三元组存储并设计相加算法。通过对比两种不同实现方案,强调了模块化和抽象思维在程序设计中的重要性。此外,还提到了Markdown编辑器的多项新功能,如图片拖拽、代码高亮、LaTeX公式和甘特图等,以提升写作体验。

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                       

本文针对数据结构基础系列网络课程(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;}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

[参考解答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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119

  对比两种方案,“参考解答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;}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
           

给我老师的人工智能教程打call!http://blog.youkuaiyun.com/jiangjunshow
这里写图片描述
你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

新的改变

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block var foo = 'bar'; 

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目Value
电脑$1600
手机$12
导管$1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列第二列第三列
第一列文本居中第二列文本居右第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPEASCIIHTML
Single backticks'Isn't this fun?'‘Isn’t this fun?’
Quotes"Isn't this fun?"“Isn’t this fun?”
Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t &ThinSpace; . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

gantt
        dateFormat  YYYY-MM-DD
        title Adding GANTT diagram functionality to mermaid
        section 现有任务
        已完成               :done,    des1, 2014-01-06,2014-01-08
        进行中               :active,  des2, 2014-01-09, 3d
        计划一               :         des3, after des2, 5d
        计划二               :         des4, after des3, 5d
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值