对于矩阵的存储,如果矩阵的元素呈有明显规律的排列的话,我们一般用一个一维数组对矩阵进行压缩存储;若矩阵中的元素多数为0,只有少数的元素为非0元素时,我们成该矩阵为稀疏矩阵
我们有矩阵Aij,其中有非0元素m个,若mij≤0.05,则我们称矩阵Aij为稀疏矩阵我们有矩阵A_{ij},其中有非0元素m个,若\frac{m}{ij} \le 0.05,则我们称矩阵A_{ij}为稀疏矩阵 我们有矩阵Aij​,其中有非0元素m个,若ijm​≤0.05,则我们称矩阵Aij​为稀疏矩阵
  对于稀疏矩阵,因为非零元素的排列是没有规律的,因此我们无法采用压缩的方法存储矩阵,而若用一个二维数组去存储含有为数不多的非零元素的矩阵,会有大量的空间浪费在存储毫无意义的0元素上,因此,对于稀疏矩阵,我们可以选择用十字链表来存储。

话不多说,先上代码

#include<stdio.h>
#include<stdlib.h>
#define FALSE 0
#define TRUE 1typedef int DataType;
typedef struct SNode
{int row;int column;union{DataType value;struct SNode *next;}uval;struct SNode *rnext;struct SNode *cnext;
}SNode, *SNodePtr;// 创建矩阵
DataType **
CreateMatrix(int row, int column);// 创造十字链表
SNodePtr
Create(int row, int column);// 向十字链表插入(如果存在则相加)
void
Insert(SNodePtr phead, SNodePtr pnode);// 将稀疏矩阵转换成十字链表存储
SNodePtr
Matrix2List(DataType **pparr, int row, int column);// 矩阵相加
SNodePtr
MatrixAdd(SNodePtr phead1, SNodePtr phead2);// 打印矩阵
void
Print(SNodePtr phead);int main()
{printf("请输入第一个矩阵\n");DataType **arr1 = CreateMatrix(4, 4);printf("\n\n请输入第二个矩阵\n");DataType **arr2 = CreateMatrix(4, 4);SNodePtr phead1 = Matrix2List(arr1, 4, 4);SNodePtr phead2 = Matrix2List(arr2, 4, 4);printf("\n\n\n");// 打印两个矩阵Print(phead1);printf("\n\n\n");Print(phead2);printf("\n\n\n");SNodePtr phead = MatrixAdd(phead1, phead2);Print(phead);return 0;
}// 创建矩阵
DataType **
CreateMatrix(int row, int column)
{DataType **ipparr = (int **)malloc(sizeof(int *) * row);for(int i = 0; i < row; ++i){ipparr[i] = (int *)malloc(sizeof(int) * column);for(int j = 0; j < column; ++j)scanf("%d", &ipparr[i][j]);}return ipparr;
}// 创造十字链表
SNodePtr
Create(int row, int column)
{// 创建头结点SNodePtr phead = (SNodePtr)malloc(sizeof(SNode));phead->row = row;phead->column = column;phead->rnext = phead->cnext = NULL;phead->uval.next = NULL;SNodePtr ptmp = phead;// 创建十字链表if(row > column){for(int i = 0; i < row; ++i){ptmp->uval.next = (SNodePtr)malloc(sizeof(SNode));ptmp = ptmp->uval.next;ptmp->row = ptmp->column = 0;ptmp->uval.next = NULL;ptmp->cnext = ptmp;if(i < column)ptmp->rnext = ptmp;else ptmp->rnext = NULL;}}else{for(int i = 0; i < column; ++i){ptmp->uval.next = (SNodePtr)malloc(sizeof(SNode));ptmp = ptmp->uval.next;ptmp->row = ptmp->column = 0;ptmp->uval.next = NULL;ptmp->rnext = ptmp;if( i < row)ptmp->cnext = ptmp;elseptmp->cnext = NULL;}}return phead;
}// 向十字链表插入(如果存在则相加)
void
Insert(SNodePtr phead, SNodePtr pnode)
{SNodePtr prtmp = phead;// 找到对应行for(int i = 0; i < pnode->row; ++i)prtmp = prtmp->uval.next;SNodePtr ptmp1 = prtmp;// 找到要插入的地方while(ptmp1->cnext != prtmp && ptmp1->cnext->column < pnode->column)ptmp1 = ptmp1->cnext;if(ptmp1->cnext->column !=  pnode->column)      {SNodePtr ptmp = (SNodePtr)malloc(sizeof(SNode));      // 新开辟空间使为了不改变pnode的指针ptmp->cnext = ptmp1->cnext;ptmp1->cnext = ptmp;ptmp->column = pnode->column;ptmp->row = pnode->row;ptmp->uval.value = pnode->uval.value;ptmp->rnext = NULL;// 接下来要将行指针连接SNodePtr pctmp = phead;// 找到对应列for(int i = 0; i < pnode->column; ++i)pctmp = pctmp->uval.next;SNodePtr ptmp2 = pctmp;// 找到要插入的地方while(ptmp2->rnext != pctmp && ptmp2->rnext->row < pnode->row)ptmp2 = ptmp2->rnext;ptmp->rnext = ptmp2->rnext;ptmp2->rnext = ptmp;return ;}else     // 这一行有非零元素且他们在同一列{ptmp1->cnext->uval.value += pnode->uval.value;return ;        // 因为没有开辟新的空间,原来的结构不变,因此不需要对列进行操作,直接返回即可}}// 将稀疏矩阵转换成十字链表存储
SNodePtr
Matrix2List(DataType **pparr, int row, int column)
{SNodePtr phead = Create(row, column);     // 创建十字链表// 创建并初始化临时指针SNodePtr ptmp = (SNodePtr)malloc(sizeof(SNode));ptmp->row = ptmp->column = 0;ptmp->uval.value = 0;ptmp->rnext = ptmp->cnext = NULL;for(int i = 0; i < row; ++i){for(int j = 0; j < column; ++j){if(pparr[i][j] != 0){ptmp->row = i + 1;ptmp->column = j + 1;ptmp->uval.value = pparr[i][j];Insert(phead, ptmp);}}}return phead;
}// 矩阵相加
SNodePtr
MatrixAdd(SNodePtr phead1, SNodePtr phead2)
{if(phead1->row != phead2->row || phead1->column != phead2->column)       // 矩阵无法相加return NULL;SNodePtr phead = Create(phead1->row, phead1->column);// 将phead1加入pheadSNodePtr ptmp = phead1;for(int i = 0; i < phead1->row; ++i){ptmp = ptmp->uval.next;SNodePtr ptmp2 = ptmp;while(ptmp2->cnext != ptmp){ptmp2 = ptmp2->cnext;Insert(phead, ptmp2);}}Print(phead);// 将phead2加入pheadptmp = phead2;for(int i = 0; i < phead2->row; ++i){ptmp = ptmp->uval.next;SNodePtr ptmp2 = ptmp;while(ptmp2->cnext != ptmp){ptmp2 = ptmp2->cnext;Insert(phead, ptmp2);}}return phead;
}// 打印矩阵
void
Print(SNodePtr phead)
{SNodePtr prtmp = phead;for(int i = 0; i < phead->row; ++i){prtmp = prtmp->uval.next;SNodePtr pctmp = prtmp->cnext;if(pctmp == prtmp){printf("0 0 0 0 ");continue;}for(int j = 1; j <= pctmp->column; ++j){if(j < pctmp->column)printf("0 ");else{printf("%d ", pctmp->uval.value);pctmp = pctmp->cnext;if(pctmp == prtmp){for(int k = phead->column; k > j; --k)printf("0 ");break;}}}printf("\n");}printf("\n");
}

  我的基本思想是对于矩阵的操作是不会影响原矩阵,即A + B = C,C不是将A加入B或者B加入A得到的,而是新开辟的一块空间。基于此思想,在进行插入操作的时候,我并没有对待插入的结点的指针做任何转变,而是找到要插入的位置,新开辟一块空间,将待插入结点的值,行列等赋值给新开辟的空间,然后再连接插入的结点的行列指针即可。基于此思想,我们在执行矩阵A和B的相加的时候,完全不用考虑矩阵A和矩阵B中指针的变动,只需要创建一个新的空的十字链表,然后将A和B中的元素插入即可。

十字链表存储稀疏矩阵相关推荐

  1. 多重链表 十字链表存储稀疏矩阵,中缀表达式

    第一个term是说该矩阵有4行5列 7个非零元素 为入口 转载于:https://blog.51cto.com/13930723/2362035

  2. 稀疏矩阵的十字链表存储表示和实现(第五章 P104 算法5.4)

    稀疏矩阵的十字链表存储 当矩阵的非零元个数和位置在操作过程中变化较大时,就不宜采用顺序存储结构来表示三元组的线性表.对这种类型的矩阵,采用链式存储结构表示三元组的线性表更为恰当. 在链表中,每个非零元 ...

  3. 稀疏矩阵十字链表类java_稀疏矩阵的十字链表存储表示

    typedef struct OLNode{ int  i,j;                 //该非零元的行列下标 ElemType    e; struct  OLNode    *right ...

  4. 5.3稀疏矩阵的十字链表存储

    十字链表产生原因:当矩阵的非零元个数和位置在操作过程中变化较大时,就不宜采用顺序存储结构来表示三元组的线性表. 十字链表特点: 每一个非零元开用含5个域的结点表示,其中i.j和e这3个域分别表示该非零 ...

  5. 【swjtu】数据结构实验5_基于十字链表的稀疏矩阵转置

    实验内容及要求: 编写程序,从字符文件读入三个正整数m, n, t以及t个三元组(i, j, e)建立稀疏矩阵的十字链表存储结构.其中,m.n分别表示矩阵行数和列数:i,  j为非零元素行号和列号.编 ...

  6. c语言建立并存储树,利用十字链表存储树结构(便于同时求出某一点的入度与出度)------C语言实现...

    #include #include #include /* 利用十字链表存储有向图,可用于同时查找某个顶点的出度与入度: */ typedef struct edge {//顶点表 int headv ...

  7. 图十字链表并求度c语言,利用十字链表存储树结构(便于同时求出某一点的入度与出度)------C语言实现...

    #include #include #include /* 利用十字链表存储有向图,可用于同时查找某个顶点的出度与入度: */ typedef struct edge{//顶点表 int headve ...

  8. 有向图的十字链表存储

    /* c7-3.h 有向图的十字链表存储表示 */#define MAX_VERTEX_NUM 20typedef struct ArcBox{int tailvex,headvex; /* 该弧的尾 ...

  9. 图的十字链表存储结构

    前面介绍了图的邻接表存储法,本节继续讲解图的另一种链式存储结构--十字链表法. 与邻接表不同,十字链表法仅适用于存储有向图和有向网.不仅如此,十字链表法还改善了邻接表计算图中顶点入度的问题. 十字链表 ...

  10. 图的十字链表存储法详解

    前面介绍了图的邻接表存储法,本节继续讲解图的另一种链式存储结构--十字链表法. 与邻接表不同,十字链表法仅适用于存储有向图和有向网.不仅如此,十字链表法还改善了邻接表计算图中顶点入度的问题. 十字链表 ...

最新文章

  1. 配置bind主域名服务器
  2. Windows 7使用wubi硬盘安装Ubuntu (文字版)
  3. 利用优盘安装win2008r2系统
  4. cnn卷积神经网络_卷积神经网络(CNN)原理及应用
  5. c语言安卓贪吃蛇代码下载,C语言贪吃蛇代码
  6. Shell脚本语法2
  7. 《JavaScript面向对象精要》——第1章 原始类型和引用类型 1.1 什么是类型
  8. Django之form组件is_valid校验机制
  9. win11错误代码0xc1900101怎么解决 windows11错误代码0xc1900101的解决方法
  10. opencv 图像处理应用之车道检测
  11. 机器学习笔记(十二):随机梯度下降
  12. CSS制作一个半透明边框
  13. Elasticsearch常用搜索和分词器
  14. linux 3.0实时性,如何1分钟内对 Linux 性能快速分析(113资讯网)
  15. 详谈如何实现手机浏览器跳转微信指定页面加好友及跳转微信公众号一键关注
  16. window下搭建php环境
  17. js:nodejs简单的Http服务器搭建
  18. 卖场型旗舰店好入驻吗?需要什么资料?
  19. Audit login 与 Audit logout
  20. ubuntu云输入法ibus cloud pinyin

热门文章

  1. android谷歌安装插件,安卓手机安装CHROME插件
  2. excel中提取中文拼音
  3. 数字图像处理(冈萨雷斯 第三版)
  4. H5+APP安卓原生插件开发+离线打包
  5. UniWebview Bug处理记录
  6. 【perl脚本】单行循环正则匹配
  7. 埃斯顿工业机器人控制柜_埃斯顿estun伺服电机动力线MS3108B22-22S BDM-GA14
  8. 洛谷P2525 Uim的情人节礼物·其之壱
  9. Win10 桌面美化
  10. PyQT5一起学做图书管理系统(2)初始化数据库