算法导论 第四章:分治法(二)

原创 2015年07月13日 19:04:19

矩阵乘法问题

    设矩阵A,B是nxn的方阵,我们将用分治法求解 C=A*B 。

     我们用蛮力方法求解的运行时间复杂度为:。利用分治法,将A,B,C划分成4个n/2 x n/2 的矩阵,如下:

                              

所以有:

                                  

采用分治思想,其伪代码表示如下:

其时间复杂度为:

为减小时间复杂度,采用Strassen 法,其原理仍将讲矩阵A,B,C划分成n/2 x n/2 ,然后按如下计算:

其时间复杂度为:


两种分治方法的完整代码如下:

#include<iostream>
#include<fstream>
#include<cmath>
#include<string>
#include<ctime>
#include<cstdlib>
#include<iomanip>
using namespace std;

void Print(int **M,int n)
{//Print the Matrix
	for(int i=0;i<n;i++)
  	{ 
		for(int j=0;j<n;j++)
			cout<<setw(5)<<M[i][j];
		cout<<endl;
		}
	}
int **AllocSize(int n)
{//malloc size for Matrix
	int **M;
	M=new int*[n];
	for(int i=0;i<n;i++)
		M[i]=new int[n];
	return M;
	}

int **getMatrix(int n)
{//Randomly generate Matrix 
	int **M;
	//srand((unsigned)time(NULL));  //generate the same random number
	M=AllocSize(n);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			M[i][j]=rand()%9+1;
	return M;
	}
void Matrix_Divide(int **A,int **A11,int **A12,int **A21,int **A22,int n)
{//Divide Matrix A into A11,A12,A21,A22
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		{ 
			A11[i][j]=A[i][j];
			A12[i][j]=A[i][j+n];
			A21[i][j]=A[i+n][j];
			A22[i][j]=A[i+n][j+n];
 			} 
	}

int **Matrix_Sub(int **A,int **B,int n)
{//Matrix Sub
	int **C;
	C=AllocSize(n);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			C[i][j]=A[i][j]-B[i][j];
	return C;
	}

int **Matrix_Add(int **A,int **B,int n)
{//Matrix Add
	int **C;
	C=AllocSize(n);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			C[i][j]=A[i][j]+B[i][j];
	return C;
	}

void Matrix_Unit(int **C,int **C11,int **C12,int **C21,int **C22,int n)
{//Unit Matrix C11,C12,C21,C22 into Matrix C
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
 		{  
			C[i][j]    =C11[i][j];
			C[i][j+n]  =C12[i][j];
			C[i+n][j]  =C21[i][j];
			C[i+n][j+n]=C22[i][j];
  			}
	}

int **DC_MatrixMul(int **A,int **B,int n)
{//Matrix Multiplication using Divide-and-Conquer
	int **C;
	C=AllocSize(n);

	if(n==1)
		C[0][0]=A[0][0]*B[0][0];
	else
	 {
		n=n/2;
		int **A11,**A12,**A21,**A22;
		int **B11,**B12,**B21,**B22;
		int **C11,**C12,**C21,**C22;
		int **T1,**T2;
		A11=AllocSize(n);
		A12=AllocSize(n);
		A21=AllocSize(n);
		A22=AllocSize(n);
		B11=AllocSize(n);
		B12=AllocSize(n);
		B21=AllocSize(n);
		B22=AllocSize(n);
		C11=AllocSize(n);
		C12=AllocSize(n);
		C21=AllocSize(n);
		C22=AllocSize(n);
		T1=AllocSize(n);    //temporary Matrix T1,T2
		T2=AllocSize(n);

		Matrix_Divide(A,A11,A12,A21,A22,n);
		Matrix_Divide(B,B11,B12,B21,B22,n);

		T1=DC_MatrixMul(A11,B11,n);
		T2=DC_MatrixMul(A12,B21,n);
		C11=Matrix_Add(T1,T2,n);

		T1=DC_MatrixMul(A11,B12,n);
	    T2=DC_MatrixMul(A12,B22,n);
	    C12=Matrix_Add(T1,T2,n);

		T1=DC_MatrixMul(A21,B11,n);
		T2=DC_MatrixMul(A22,B21,n);
		C21=Matrix_Add(T1,T2,n);

		T1=DC_MatrixMul(A21,B12,n);
		T2=DC_MatrixMul(A22,B22,n);
		C22=Matrix_Add(T1,T2,n);

		Matrix_Unit(C,C11,C12,C21,C22,n);		
 	 	}  
	return C;
	}

int **Strassen_MatrixMul(int **A,int **B,int n)
{
	int **C;
	C=AllocSize(n);

	if(n==1)
		C[0][0]=A[0][0]*B[0][0];
	else
  	 { 
		n=n/2;
		int **A11,**A12,**A21,**A22;
		int **B11,**B12,**B21,**B22;
		int **C11,**C12,**C21,**C22;
		int **S1,**S2,**S3,**S4,**S5,**S6,**S7,**S8,**S9,**S10;
		int **P1,**P2,**P3,**P4,**P5,**P6,**P7;
		int **T1,**T2;

		A11=AllocSize(n);
		A12=AllocSize(n);
		A21=AllocSize(n);
		A22=AllocSize(n);
		B11=AllocSize(n);
		B12=AllocSize(n);
		B21=AllocSize(n);
		B22=AllocSize(n);
		C11=AllocSize(n);
		C12=AllocSize(n);
		C21=AllocSize(n);
		C22=AllocSize(n);
		
		S1 =AllocSize(n);
		S2 =AllocSize(n);
		S3 =AllocSize(n);
		S4 =AllocSize(n);
		S5 =AllocSize(n);
		S6 =AllocSize(n);
		S7 =AllocSize(n);
		S8 =AllocSize(n);
		S9 =AllocSize(n);
		S10=AllocSize(n);
		
		P1 =AllocSize(n);
		P2 =AllocSize(n);
		P3 =AllocSize(n);
		P4 =AllocSize(n);
		P5 =AllocSize(n);
		P6 =AllocSize(n);
		P7 =AllocSize(n);

		T1=AllocSize(n);    
		T2=AllocSize(n);   
       
		Matrix_Divide(A,A11,A12,A21,A22,n);
		Matrix_Divide(B,B11,B12,B21,B22,n);

		S1 =Matrix_Sub(B12,B22,n);
		S2 =Matrix_Add(A11,A12,n);
		S3 =Matrix_Add(A21,A22,n);
		S4 =Matrix_Sub(B21,B11,n);
		S5 =Matrix_Add(A11,A22,n);
		S6 =Matrix_Add(B11,B22,n);
		S7 =Matrix_Sub(A12,A22,n);
		S8 =Matrix_Add(B21,B22,n);
		S9 =Matrix_Sub(A11,A21,n);
		S10=Matrix_Add(B11,B12,n);

		P1=Strassen_MatrixMul(A11,S1,n);
		P2=Strassen_MatrixMul(S2,B22,n);
		P3=Strassen_MatrixMul(S3,B11,n);
		P4=Strassen_MatrixMul(A22,S4,n);
		P5=Strassen_MatrixMul(S5, S6,n);
		P6=Strassen_MatrixMul(S7, S8,n);
		P7=Strassen_MatrixMul(S9,S10,n);
		
		
		T1 =Matrix_Add(P5,P4,n);
		T2 =Matrix_Sub(P2,P6,n);
		C11=Matrix_Sub(T1,T2,n);

		C12=Matrix_Add(P1,P2,n);
		C21=Matrix_Add(P3,P4,n);

		T1 =Matrix_Add(P5,P1,n);
		T2 =Matrix_Add(P3,P7,n);
		C22=Matrix_Sub(T1,T2,n);

		Matrix_Unit(C,C11,C12,C21,C22,n);		
 	  	} 
	

	return C;
	}
int main()
{
	int n=4;
	int **A,**B,**C;
	cout<<"The maxtrix A is:"<<endl;
	A=getMatrix(n);
	Print(A,n);
	cout<<"The matrix B is:"<<endl;
	B=getMatrix(n);
	Print(B,n);
	cout<<"The DC_mul result C is:"<<endl;
	C=DC_MatrixMul(A,B,n);
	Print(C,n);
	cout<<"The Strassen_mul result C is:"<<endl;
	C=Strassen_MatrixMul(A,B,n);
	Print(C,n);
	
	return 0;
	}

运行结果如下:





 




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

《算法导论》读书笔记(二)——分治法

设计算法 插入排序使用了增量法,即先排j-1个,然后排j个,下面学习一种新的方法:分治法。 分治法 分治法的思想:大事化小,分而治之。把规模较大的问题分解为几个规模较小的类似子问题,递归的求解子问题,...

[算法导论]分治法---最大子数组

分治策略---最大自子数组 一、分治策略的三个步骤 1、分解:将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小 2、解决:递归地求解出子问题。如果子问题的规模足够小...

算法导论-分治法-最近点对-HDOJ1007

HDOJ1007的原题目是求出在不同时套中两个玩具的前提下,圆圈的最大半径。问题翻译过来就是求解最近点对的问题,这个问题是经典的分治法问题。 参考博客:http://www.cnblogs.com/p...
  • jkhere
  • jkhere
  • 2014年03月20日 10:38
  • 3213

【算法导论】分治法及归并排序

有很多算法,在结构上他们是递归的:weile
  • Eaton18
  • Eaton18
  • 2014年09月18日 00:39
  • 352

MIT算法导论学习笔记-Lecture4 分治法(续)

第四讲:分治法(续) 4.1 快速排序(Quicksort)

算法导论之分治法

分治法:主要算法思想就是divide and conquer

算法导论第二版笔记之分治法

//朴素的算法     解决a的n次方相乘问题 #include #include   usingnamespace std; int main() {     double a; ...

算法导论学习1--分治法计算逆序数

闲来无事,复习复习经典的算法导论。看到了2-4,习题,计算逆序数的问题,忍不住实现了一下。   逆序数,是排列组合中常见的一个指标,可以用来衡量一个数列的杂乱成对(相对于顺序排列),在一些算法如水...
  • cpfeed
  • cpfeed
  • 2011年09月06日 00:43
  • 4232

算法导论学习2.3 分治法 (这个递归终于懂了。。)

import java.util.Arrays; public class MergeSort { public static void main(String[] args) { ...

算法导论——分治法——最大子数组问题

好久没有写博客了。以后我会不定期地写一些算法的博客,分享一些算法的感想。以下的说法很多都是我自己的感想,肯定有很多不足的地方,希望大家指正。 今天把算法导论里面分治法这一章里面的第一个问题——最大子数...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:算法导论 第四章:分治法(二)
举报原因:
原因补充:

(最多只允许输入30个字)