Strassen算法
如题,该算法是来自德国的牛逼的数学家strassen搞出来的,因为把n*n矩阵之间的乘法复杂度降低到n^(lg7)(lg的底是2),一开始想当然地认为朴素的做法是n^3,哪里还能有复杂度更低的做法,但是牛逼的strassen先生简直刷新了我的线性代数观和算法观
好吧,回来添一句:其实这个好理解,为何我一开始认为朴素计算方法是唯一的做法(而且为何还有strassen这样复杂度进一步降低的算法),举个例子:(A+B)(C+D),怎么做合适?先加后乘:两次加法,一次乘法;先乘后加:经历四次乘法和四次加法。可见,不同的计算步骤,计算代价是不同的。strassen就是玩这种拆拆合合的玩意儿搞出来这么个算法,不过人家那数学功底是真的好!
思路:基本的思路网上有,此处不再赘述,下面说说怎么实现strassen算法(数据处理)
m*n的矩阵和n*p的矩阵相乘,得到m*p的矩阵,因为每次要二分,遇到奇数的做法就是在行尾(列尾)加全零行(列),因为加入全零行(列)是不会影响就算结果的,从而使得可以二分。我为了省事直接在输入两个矩阵后就直接把它们统一扩展成了2^y*2^y的矩阵,其中,y=2^「lg(Max{m,p})」 (「」是向上取整,输入法里没找到合适的符号....;另外,Max(m,n)和Max(n,p)是相等的,取哪个都一样)
代码:
# include <iostream.h>
# include "..\Sort\IO_tools.cpp"
void strassen(int** &C,int** &A,int** &B,int arow,int acol,int brow,int bcol,int size);
void stra_plus(int** &C,int** &A,int** &B,int crow,int ccol,int arow,int acol,int brow,int bcol,int size,int symbol);
void main(){
int** A=NULL;int** B=NULL;int** C=NULL;
int A_row,A_col,B_row,B_col,size;
cout<<"size of A<row,col>:"<<endl;
cin>>A_row>>A_col;
size=input2A(A,A_row,A_col);//万能的传引用,绝对正确!
cout<<"size of B<row,col>:"<<endl;
cin>>B_row>>B_col;
input2A(B,B_row,B_col);//万能的传引用,绝对正确!
strassen(C,A,B,0,0,0,0,size);
output2A(C,A_row,B_col);
//stra_plus(C,A,B,0,0,0,0,0,0,size,1);
//output2A(C,size,size);
}
void strassen(int** &C,int** &A,int** &B,int arow,int acol,int brow,int bcol,int size){
C=(int**)new int* [size];
for(int i=0;i<size;i++){
C[i]=new int[size];
}
/*
对于size>1的要进一步拆分(其实strassen算法递归计算时要申请这么多内存,size不够大时反而降低了效率,
故而size达到下限时可以采用朴素的矩阵乘法计算方法而不必继续调用strassen算法,此处出于偷懒就省点事儿把size下限设为1)
*/
if(size>1){
//S(1-10)初始化
int** S1=NULL;int** S2=NULL;int** S3=NULL;int** S4=NULL;int** S5=NULL;int** S6=NULL;int** S7=NULL;int** S8=NULL;int** S9=NULL;int** S10=NULL;
stra_plus(S1,B,B,0,0,brow,bcol+size/2,brow+size/2,bcol+size/2,size/2,-1);
stra_plus(S2,A,A,0,0,arow,acol,arow,acol+size/2,size/2,1);
stra_plus(S3,A,A,0,0,arow+size/2,acol,arow+size/2,acol+size/2,size/2,1);
stra_plus(S4,B,B,0,0,brow+size/2,bcol,brow,bcol,size/2,-1);
stra_plus(S5,A,A,0,0,arow,acol,arow+size/2,acol+size/2,size/2,1);
stra_plus(S6,B,B,0,0,brow,bcol,brow+size/2,bcol+size/2,size/2,1);
stra_plus(S7,A,A,0,0,arow,acol+size/2,arow+size/2,acol+size/2,size/2,-1);
stra_plus(S8,B,B,0,0,brow+size/2,bcol,brow+size/2,bcol+size/2,size/2,1);
stra_plus(S9,A,A,0,0,arow,acol,arow+size/2,acol,size/2,-1);
stra_plus(S10,B,B,0,0,brow,bcol,brow,bcol+size/2,size/2,1);
//P(1-7)初始化
int** P1=NULL;int** P2=NULL;int** P3=NULL;int** P4=NULL;int** P5=NULL;int** P6=NULL;int** P7=NULL;
strassen(P1,A,S1,arow,acol,0,0,size/2);
strassen(P2,S2,B,0,0,brow+size/2,bcol+size/2,size/2);
strassen(P3,S3,B,0,0,brow,bcol,size/2);
strassen(P4,A,S4,arow+size/2,acol+size/2,0,0,size/2);
strassen(P5,S5,S6,0,0,0,0,size/2);
strassen(P6,S7,S8,0,0,0,0,size/2);
strassen(P7,S9,S10,0,0,0,0,size/2);
//计算结果C(依次是C11,C12,C21,C22)
stra_plus(C,P4,P5,0,0,0,0,0,0,size/2,1);stra_plus(C,C,P2,0,0,0,0,0,0,size/2,-1);stra_plus(C,C,P6,0,0,0,0,0,0,size/2,1);
stra_plus(C,P1,P2,0,size/2,0,0,0,0,size/2,1);
stra_plus(C,P3,P4,size/2,0,0,0,0,0,size/2,1);
stra_plus(C,P5,P1,size/2,size/2,0,0,0,0,size/2,1);stra_plus(C,C,P3,size/2,size/2,size/2,size/2,0,0,size/2,-1);stra_plus(C,C,P7,size/2,size/2,size/2,size/2,0,0,size/2,-1);
}
/*到达下限*/
else{
C[0][0]=A[arow][acol]*B[brow][bcol];
}
}
//参与运算的是A,B,C的size*size的(子)矩阵,<arow,acol>是A的参与运算的子矩阵的左上角坐标,<brow,bcol>同理,C是保存结果的
void stra_plus(int** &C,int** &A,int** &B,int crow,int ccol,int arow,int acol,int brow,int bcol,int size,int symbol){
if(C==NULL){
C=(int**)new int* [size];
for(int i=0;i<size;i++){
C[i]=new int[size];
}
}
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
C[i+crow][j+ccol]=A[i+arow][j+acol]+symbol*B[i+brow][j+bcol];
}
}
}
# include <iostream.h>
# include <stdlib.h>
# include <math.h>
int get_Upper_2Pow(int row,int col);
void inputA(int A[],int n){
int i=n;
cout<<"Input Array:";
while(i--){
cin>>A[n-i-1];
}
}
void outputA(int A[],int n){
int i=n;
cout<<"output Array:";
while(i--){
cout<<A[n-i-1]<<" ";
}
cout<<endl;
}
int input2A(int** &A,int row,int col){
int size=get_Upper_2Pow(row,col);
A=(int**)new int* [size];
for(int i=0;i<size;i++){
A[i]=new int[size];
}
cout<<"Input 2th Array:"<<endl;
for(int r=0;r<size;r++){
for(int c=0;c<size;c++){
A[r][c]=0;
}
}
for(r=0;r<row;r++){
for(int c=0;c<col;c++){
cin>>A[r][c];
}
}
return size;
}
void output2A(int** A,int row,int col){
cout<<"output:"<<endl;
for(int r=0;r<row;r++){
for(int c=0;c<col;c++){
cout<<A[r][c]<<" ";
}
cout<<endl;
}
}
int get_Upper_2Pow(int row,int col){
for(int i=0;pow(2,i)<row||pow(2,i)<col;i++);
return (int)pow(2,i);
}
Strassen算法的更多相关文章
- Conquer and Divide经典例子之Strassen算法解决大型矩阵的相乘
在通过汉诺塔问题理解递归的精髓中我讲解了怎么把一个复杂的问题一步步recursively划分了成简单显而易见的小问题.其实这个解决问题的思路就是算法中常用的divide and conquer, 这篇 ...
- 第四章 分治策略 4.2 矩阵乘法的Strassen算法
package chap04_Divide_And_Conquer; import static org.junit.Assert.*; import java.util.Arrays; import ...
- 4-2.矩阵乘法的Strassen算法详解
题目描述 请编程实现矩阵乘法,并考虑当矩阵规模较大时的优化方法. 思路分析 根据wikipedia上的介绍:两个矩阵的乘法仅当第一个矩阵B的列数和另一个矩阵A的行数相等时才能定义.如A是m×n矩阵和B ...
- 《算法导论》——矩阵乘法的Strassen算法
前言: 很多朋友看到我写的<算法导论>系列,可能会觉得云里雾里,不知所云.这里我再次说明,本系列博文时配合<算法导论>一书,给出该书涉及的算法的c++实现.请结合<算法导 ...
- 算法导论-矩阵乘法-strassen算法
目录 1.矩阵相乘的朴素算法 2.矩阵相乘的strassen算法 3.完整测试代码c++ 4.性能分析 5.参考资料 内容 1.矩阵相乘的朴素算法 T(n) = Θ(n3) 朴素矩阵相乘算法,思想明了 ...
- 【算法导论C++代码】Strassen算法
简单方阵矩乘法 SQUARE-MATRIX-MULTIPLY(A,B) n = A.rows let C be a new n*n natrix to n to n cij = to n cij=ci ...
- 整数快速乘法/快速幂+矩阵快速幂+Strassen算法
快速幂算法可以说是ACM一类竞赛中必不可少,并且也是非常基础的一类算法,鉴于我一直学的比较零散,所以今天用这个帖子总结一下 快速乘法通常有两类应用:一.整数的运算,计算(a*b) mod c 二.矩 ...
- 【C++】Strassen算法代码
本文仅代码,无理论解释 实话实说,我觉得这个算法在C系列的语言下,简直垃圾到爆炸--毕竟是一群完全不懂程序数学家对着纸弄出来的,看起来好像非常的有用,实际上耗时是非常爆炸的. 但是<算法导论&g ...
- 【算法导论】--分治策略Strassen算法(运用下标运算)【c++】
由于偷懒不想用泛型,所以直接用了整型来写了一份 ①首先你得有一个矩阵的class Matrix ②Matrix为了方便用下标进行运算, Matrix的结构如图:(我知道我的字丑...) Matrix. ...
随机推荐
- hdu - 1829 A Bug's Life (并查集)&&poj - 2492 A Bug's Life && poj 1703 Find them, Catch them
http://acm.hdu.edu.cn/showproblem.php?pid=1829 http://poj.org/problem?id=2492 臭虫有两种性别,并且只有异性相吸,给定n条臭 ...
- hihoCoder 1043 完全背包 (dp)
http://hihocoder.com/problemset/problem/1043 动态转移方程 :for v=cost..V f[v]=max(f[v],f[v-c[i]]+w[i]); #i ...
- 《OD大数据实战》Storm环境搭建
一.环境搭建 1. 下载 http://www.apache.org/dyn/closer.lua/storm/apache-storm-0.9.6/apache-storm-0.9.6.tar.gz ...
- URAL1900 Brainwashing Device(dp)
1900 二维dp挺好推 dp[i][j] = max(dp[i][j],dp[g][j-1]+o[i][i+1]-o[g][i+1])(i>g>=j-1) dp[i][j]表示第i个站台 ...
- 使用spring @Scheduled注解执行定时任务
以前框架使用quartz框架执行定时调度问题. 老大说这配置太麻烦.每个调度都需要多加在spring的配置中. 能不能减少配置的量从而提高开发效率. 最近看了看spring的 scheduled的使用 ...
- Spring MVC 下index.jsp访问
spring-mvc.xml配置 <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 --> <bean class="org.springframework.we ...
- Windows Live Writer配置测试
文字可以了 不知道代码怎么发布
- LeetCode——Add Two Numbers
Question:You are given two linked lists representing two non-negative numbers. The digits are stored ...
- windows7操作系统64位安装ArcSDE10.1和Oracle11g
安装环境如下: Oracle11g R2 64位服务端Oracle11g R2 32位客户端(管理员,第二项)ArcSDE10.1 for Oracle11g SDE数据库可由其它机器安装Arcata ...
- tomcat Manger App
转发链接,嘿嘿http://simeon.blog.51cto.com/18680/58877