黑马程序员____矩阵相乘常规法和Strassen方法算法分析

算法 专栏收录该内容
6 篇文章 0 订阅

----------------------android培训java培训、期待与您交流! ----------------------

矩阵相乘是计算机编程领域的常见问题。按照常规方法解决问题的算法复杂度为,在矩阵规模超过一定规模后,复杂度增长使得计算时间过长,无法令人满意。显然,矩阵相乘的下界在,但这个想法过于理想。目前得到的最优方案为,由于最优方案的实现过于复杂,没有在计算机上完美实现。Strassen方法通过分治递归的思想,将算法的复杂度降到了左右,并且实现较为简单。本实验的目的就是在程序实现矩阵相乘常规法和Strassen方法的基础上,比较两者在不同数据规模下的速度。

一、 算法分析

1. 矩阵相乘常规法

伪码实现如下:

MATRIX-MULTIPLY(A, B)

n rows[A]

let C be an n × n matrix

for i 1 to n

do for j 1 to n

do cij 0

for k 1 to n

do cij cij + aik× bkj

return C

通过伪代码循环嵌套的分析,可以直观地看出算法复杂度为

2. 矩阵相乘Strassen

将一个 n × n的矩阵乘法分割为 2 × 2(n/2) × (n/2)大小的子矩阵相乘。

P1=a (fh)

P2= (a+ b)h

P3= (c+ d)e

P4=d (ge)

P5= (a+ d)(e+h)

P6= (bd)(g+h)

P7= (ac)(e+f )

r =P5+ P4P2+P6

s =P1+ P2

t =P3+ P4

u =P5+ P1P3P7

这样在子矩阵的加乘法中,一共涉及到7次乘法,由于在大规模矩阵的情况下,矩阵相乘的复杂度远大于加减矩阵的复杂度,所以Strassen算法比常规法有所改进(Strassen方法的正确性在此略过)。

算法复杂度得到一定的改进。

二、程序实现

关键步骤说明

程序在实现的过程中。有时会碰到分割出的矩阵的n不为偶数的情形,此时应对矩阵加一条零边,使分割顺利进行,而不影响计算结果。

分割出的矩阵使用动态二维矩阵存储,节约存储空间。在矩阵使用完以后及时回收,以免堆内存溢出。

三、测试程序

范例测试(正确性测试)
The Source matrix is displayed below:

1 7 4 0 9

4 8 8 2 4

5 5 1 7 1

1 5 2 7 6

1 4 2 3 2

The Target matrix is displayed below:

2 1 6 8 5

7 6 1 8 9

2 7 9 5 4

3 1 2 3 3

4 1 1 3 8

常规法所得结论:

The Result matrix is displayed below:

95 80 58 111 156

102 114 112 154 162

72 50 59 109 103

86 58 49 97 127

51 44 36 65 74

Strassen法所得结论:

The Result matrix is displayed below:

95 80 58 111 156

102 114 112 154 162

72 50 59 109 103

86 58 49 97 127

51 44 36 65 74

根据手动计算结果,均正确。

压力测试(不同数据规模下运行速度):(单位为秒)

图表1

表格1

数据取600位上界,即超过10分钟跳出。可以看到使用Strassen算法时,耗时不但没有减少,反而剧烈增多,在n=700时计算时间就无法忍受。仔细研究后发现,采用Strassen算法作递归运算,需要创建大量的动态二维数组,其中分配堆内存空间将占用大量计算时间,从而掩盖了Strassen算法的优势。于是对Strassen算法做出改进,设定一个界限。当n<界限时,使用普通法计算矩阵,而不继续分治递归。

改进后算法优势明显,就算时间大幅下降。之后,针对不同大小的界限进行试验。在初步试验中发现,当数据规模小于1000时,下界S法的差别不大,规模大于1000以后,n取值越大,消耗时间下降。最优的界限值在32128之间。

因为计算机每次运算时的系统环境不同(CPU占用、内存占用等),所以计算出的时间会有一定浮动。虽然这样,试验结果已经能得出结论Strassen算法比常规法优势明显。使用下界法改进后,在分治效率和动态分配内存间取舍,针对不同的数据规模稍加试验可以得到一个最优的界限。

四、 实验小结

本次实验成功实现了矩阵相乘的常规法和Strassen算法,发现了Strassen算法在使用动态内存分配时的缺陷,并进行改进。实验中还发现Strassen算法消耗内存明显,在使用空间换取时间时要进行适当取舍。

---------------------- android培训java培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net/heima

  • 4
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值