当数组中非零元素非常少时,我们可以称之为稀疏矩阵。为了减少空间的浪费,在存储稀疏矩阵的时候,我们对它进行压缩存储,即指存储非零信息。

一、数组的顺序存储

在存储稀疏矩阵的时候,除了存储非零元素的值,还需要存储其行列号i和j,故每个非零元素要用一个三元组(i, j, v)来描述。因为要与矩阵的对应关系,我们还需要在三元组表中增设非零元素的个数和矩阵行列大小。

那么,稀疏矩阵的数组表达如下所示。

struct CrossNode{ //三元组结构int i, j; //行列号ElementType value; //元素值CrossNode(int idx, int jdx, ElementType val):i(idx), j(jdx), value(val){}
};class CrossList{ //三元组表结构int row, col, count; //行列数、非零元素个数CrossNode data[maxnum];
}

二、十字链表

当三元组按行列序组成一个线性表,如果数组的非零元素个数较大,元素定位的效率就会比较低下。为此,我们可以采用行列两个方向交叉的十字链表,来表示稀疏矩阵。

每个非零节点不仅要存放(i, j, e),还要存放它横向的下一个结点的地址以及纵向的下一个结点的地址,形成一个类似十字形的链表的结构,具体定义如下:

//节点结构
struct CrossNode{int i, j, value;CrossNode *right, *down;CrossNode(int idx, int jdx, int val) : i(idx), j(jdx), value(val), right(NULL), down(NULL){}
};typedef struct CrossNode CLNode, *CrossLine;//十字链表
class CrossList{
public:CrossList(){}CrossList(vector< vector<int> > &arr);//...
private://...int row, col, count;CrossLine *rowHead, *colHead;
};

这里需要注意的是,十字链表结构里的rowHead和colHead的类型是CorssLine *,也就是CrossNode * * 。

如果把它们设置为CrossNode *类型,那么后期元素的定位和访问需要行和列的遍历,效率不高。

完整程序

#include <iostream>
#include <vector>
using namespace std;//Node Denifition
struct CrossNode{int i, j, value;CrossNode *right, *down;CrossNode(int idx, int jdx, int val) : i(idx), j(jdx), value(val), right(NULL), down(NULL){}
};typedef struct CrossNode CLNode, *CrossLine;//Orthogonal List Definition
class CrossList{
public:CrossList(){}CrossList(vector< vector<int> > &arr);void Insert(CLNode* &node);void print();int getCount();
private:void InsertIntoRow(CLNode* &node);void InsertIntoColumn(CLNode* &node);void CreateSparseMatrix(vector< vector<int> > &arr);int row, col, count;CrossLine *rowHead, *colHead;
};//Constructor
CrossList::CrossList(vector< vector<int> > &arr){if(arr.empty()) return;row = arr.size();col = arr[0].size();rowHead = new CrossLine[row];for(int m = 0; m < row; ++m)rowHead[m] = NULL;colHead = new CrossLine[col];for(int n = 0; n < col; ++n)colHead[n] = NULL;CreateSparseMatrix(arr);
}//Insertion
void CrossList::Insert(CLNode* &node){InsertIntoRow(node);InsertIntoColumn(node);
}//Update rowHead when insertion
void CrossList::InsertIntoRow(CLNode* &node){int m = node->i;if(!rowHead[m]){rowHead[m] = node;}else{if(rowHead[m]->j > node->j){node->right = rowHead[m];rowHead[m] = node;}else{CLNode* cur = rowHead[m]; while(cur->right && cur->right->j < node->j){cur = cur->right;}if(!cur->right){cur->right = node;}else{node->right = cur->right;cur->right = node;}}}
}//Update colHead when insertion
void CrossList::InsertIntoColumn(CLNode* &node){int n = node->j;if(!colHead[n]){colHead[n] = node;}else{if(colHead[n]->i < node->i){node->down = colHead[n];colHead[n] = node;}else{CrossLine cur = colHead[n]; //CLNode *while(cur->down && cur->down->i < node->i){cur = cur->down;}if(!cur->down){cur->down = node;}else{node->down = cur->down;cur->down = node;}}}
}//Store sparse matrix
void CrossList::CreateSparseMatrix(vector< vector<int> > &arr){for(int m = 0; m < row; ++m){for(int n = 0; n < col; ++n){if(arr[m][n] != 0){CLNode *newNode = new CLNode(m, n, arr[m][n]);Insert(newNode);++count;}}}
}//Print sparse matrix
void CrossList::print(){for(int m = 0; m < row; ++m){CrossLine cur = rowHead[m];int n = 0;while(n < col){if(cur && n == cur->j){cout << cur->value << " ";cur = cur->right;}else cout << "0 ";++n;}cout << endl;}
}int CrossList::getCount(){ return count;
}//Test case
int main(){vector< vector<int> > arr = {{0,  18, 0,  0,  0,  0},{0,  0,  67, 0,  0,  0},{0,  0,  0,  0,  0,  41},{0,  0,  47, 62, 0,  0},{0,  0,  0,  0,  0,  35}};CrossList testList(arr);testList.print();
}

数据结构 - 十字链表之稀疏矩阵的存储相关推荐

  1. 数据结构——十字链表(C语言实现)

    十字链表是将邻接表和逆邻接表结合在一起的一种有向图的数据结构 十字链表的节点结构体表示的是一个节点到另一个节点的边,并且此由指出节点(from)和指入节点(to)共同使用,因此大大节省了内存. 先直观 ...

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

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

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

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

  4. 18、数据结构笔记之十八链表实现稀疏矩阵

    18.数据结构笔记之十八链表实现稀疏矩阵 "必须如蜜蜂一样,采过许多花,才能酿出蜜来." 上篇中实现了栈在多项式实现中的例子,再来看下稀疏矩阵通过链表方式实现. 关键字:十字链表存 ...

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

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

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

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

  7. 阿里巴巴校园招聘 —— 灵犀游戏开发测试岗笔试题目总结(菜鸡版解析)涉及知识点——十字链表、线程与堆栈、FTP、Telnet、红黑树、哈夫曼树、平衡二叉树、乐观锁、悲观锁、HTTP、NIM游戏

    内容 感觉内容无非是那几个: 数据结构与算法 + 计算机网络 + 操作系统 + C++基础语法知识 简单的送分题我就不说了,我说几个还有点迷惑性的点来整理一下: 1. 十字链表 在Linux内核中应用 ...

  8. 日撸 Java 三百行(37 天: 十字链表)

    注意:这里是JAVA自学与了解的同步笔记与记录,如有问题欢迎指正说明 目录 前言: 一.关于十字链表 1.特殊情况下邻接表的局限 2.十字链表的结构与特点 二.十字链表的代码实现 1.基本属性 2.出 ...

  9. 数据结构java稀疏矩阵_数据结构之十字链表——稀疏矩阵的链式存储及加法运算...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 以下简单实现了数据结构中的十字链表(Java实现):代码为添加(add)方法及求和(sum)方法,其它方法后续有时间再添加,最下面有测试方法 CrossL ...

最新文章

  1. 一行js_不用引入JQuery,前端开发们一行代码就能使用的提示信息开源组件
  2. 跳出数据计算拯救人工智能之自然法则
  3. 深度学习核心技术精讲100篇(四十七)-做推荐系统之余,我们该思考什么?
  4. Eclipse和MyEclipse相关的快捷键
  5. android app性能优化_Android性能优化之Apk 瘦身优化
  6. GIT命令行的一些基本操作
  7. JavaScript中数组交集的最简单代码
  8. Eureka的工作原理以及它与ZooKeeper的区别
  9. python2最新版本_Python 2.7.18发布,Python 2的最新版本
  10. hex2text php,php如通过AES加密/解密实现bin2hex和hex2bin之间的切换
  11. python导入鸢尾花数据集_python 鸢尾花数据集报表展示
  12. LOL开发者谈网游自动化测试:每天10万次
  13. python 估值模型_基于Python的客户价值细分模型(RFM)
  14. python数据可视化案例2017年6省gdp_吴裕雄 数据挖掘与分析案例实战(5)——python数据可视化...
  15. 丢手帕问题(约瑟夫问题)
  16. 华为M-LAG跨设备链路聚合技术理论讲解
  17. VSCode 常用主题收集
  18. python用smtp发邮件怎么抄送_python使用SMTP发邮件时使用Cc(抄送)和Bcc(密送)...
  19. 十个最好的免费杀毒软件下载
  20. 关于翻译文档的软件哪个比较好用,这些工具希望你知道

热门文章

  1. [iOS]iPhoto的删除动画(转)
  2. JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释
  3. 计算机系统崩溃,解答电脑系统崩溃怎么重装
  4. Rust机器学习之ndarray
  5. Java自学心得,从小白到高手的蜕变
  6. 数据结构 图基本介绍
  7. 详解:阿里邮箱_阿里企业邮箱_阿里邮箱企业版
  8. 国考省考行测:数字推理题2
  9. 两种简单的网页图片替换方法
  10. C++11新特性之 std::forward(完美转发)