我有一个大小为(8 x 8)的矩阵,如下所示,我必须将其转换为稀疏矩阵的形式,并使用C语言计算每一列的非零元素之和。
Matrix = [1 2 0 4 0 0 0 0;
0 1 3 0 2 0 0 0;
1 0 4 7 0 0 0 0;
0 6 0 0 1 8 0 0;
0 0 0 0 4 0 0 0;
0 0 0 0 8 1 1 0;
0 0 0 0 9 0 2 0;
0 0 0 0 0 0 7 1]
有人可以建议如何解决此问题吗? 请注意,这是一个示例矩阵,实际上,我有大约(15,000行x 25,000列)左右的巨大矩阵。
答案 0 :(得分:1)
有人可以建议如何解决此问题吗?
您创建一个列表,该列表存储矩阵的非零元素。为此,您需要一个结构来定义此列表的元素的外观:
struct sparseElement{
int n;
int m;
int value;
}
然后,通过循环遍历矩阵,计算非零元素,将其转换为这种稀疏形式。现在您知道有多少个了,您可以分配内存:
sparseElement* sparse = malloc(n * sizeof(sparseElement))
其中n
是非零元素的数量。然后,您可以填写列表。
使用C语言计算每一列的非零元素之和。
您可以遍历列表,并对列索引等于要为其计算总和的行的所有元素求和。如果要一次对所有列进行操作,则可以创建一个每列一个条目的列表,然后将每个元素添加到相应的索引中。
当然,这只是可能的实现。大型,成熟的图书馆使用更详尽,更有效的结构/算法。
答案 1 :(得分:1)
有人可以建议如何解决此问题吗?
找出稀疏矩阵上的所有必需操作和可选操作。
许多操作都需要按行或按列访问数据。某些运算(例如有效的朴素矩阵矩阵乘法)需要同时执行这两项操作;具体取决于矩阵在乘法运算符的哪一侧。一些操作得益于简单的移调。收集操作并按需求进行分类,可以为您提供选择最佳(对于用例而言最接近最佳)实现的标准。
选择适当的类型来描述矩阵中的值。
尤其是,我建议考虑float,double,unsigned char,signed char,uint N _t和int N _t类型(对于 N = 8、16、32或64)。
您需要精确度和范围来描述您拥有的值,而不会浪费存储空间来获得不需要的精确度或范围。
选择用于实现稀疏矩阵的数据结构。
sparse matrix上的Wikipedia文章描述了一些典型的结构(DOK,LIL,COO,CSR,CSC,Yale)。如果实现多个,则不仅需要在每个函数上编写所有低级运算,而且还需要为算术运算编写所有组合。 (例如,如果您的稀疏矩阵使用压缩稀疏行(CSR)或压缩稀疏列(CSC)格式,那么您将需要四个矩阵矩阵乘法例程,具体取决于两个参数矩阵的类型(CSR×CSR, CSC×CSR,CSR×CSC,CSC×CSC),因为矩阵乘法不是可交换的。)
如果性能很重要,则应仔细考虑各种数据结构的缓存效果。您需要按一个或多个数组顺序检查内存,以利用CPU预取和缓存的优势。如果有大量数据,您将希望尽可能“紧凑”地打包所有内容(因为内存带宽往往是矩阵运算的限制瓶颈),但应将处理每个矩阵元素所需的运算减至最少。 br />
编写基本的矩阵输入/输出例程和单元测试,以检查数据结构是否正常工作。
通常,您需要在文件或流(如标准输入和输出)中读写这些矩阵。先写那些。然后,编写一些调试函数来描述如何存储矩阵数据。至少,您需要编写一个测试程序,该程序读取矩阵(从标准输入),打印矩阵(至标准输出)和存储格式(至标准错误);您可以为它提供一些测试用例输入(至少一个带有随机数据),以查看往返是否保留正确的数据。我经常使用awk来生成测试数据集,并将数值输出与期望的数值输出进行比较。
写一个给定稀疏矩阵 M 的函数,返回行向量 v ,其中 v i = ∑ M j , i
换句话说, v 中的元素 i 是列 i 中 M 的所有元素的总和。
为您的功能编写一个测试程序,然后对其进行测试。
通常,您希望程序从标准输入读取矩阵,然后将向量写入标准输出。