分治法 矩陣乘法

2021-10-24 21:40:29 字數 3078 閱讀 9447

問題:給定兩個n階方陣相乘,對求解演算法進行優化。

首先,根據傳統演算法,兩個n階矩陣相乘,對於n2個元素,每個元素想要被計算出來,至少要進行n次乘法和n-1次加法,演算法複雜度達到o(n3)。

考慮將矩陣分塊,分為4個n/2的方陣,那麼每個兩個小方陣相乘的複雜度為o(n3)/8,要想得出最終結果,一共需要8次小方陣相乘,複雜度沒有減小。

為了減小複雜度,必須減小相乘的次數。

strassen乘法:通過數學構造,將8個不同的小方陣轉化為7個不同的小方陣,從而減少相乘的次數。

**:

#include using namespace std;

void matrixadd(int **a,int **b,int **c,int n)

void matrixsub(int **a,int **b,int **c,int n)

// 用strassen演算法計算矩陣a與b的乘積,儲存在矩陣c中

// 輸入:矩陣a,b,c,矩陣維數n

void matrixmulti(int **a,int **b,int **c,int n)else

//分割輸入矩陣a和b

for(int i = 0;i < n/2;i++)

}//計算p1~p7

matrixadd(a11, a22, as, n/2);

matrixadd(b11, b22, bs, n/2);

matrixmulti(as, bs, p1, n/2);

matrixadd(a21, a22, as, n/2);

matrixmulti(as, b11, p2, n/2);

matrixsub(b12, b22, bs, n/2);

matrixmulti(a11, bs, p3, n/2);

matrixsub(b21, b11, bs, n/2);

matrixmulti(a22, bs, p4, n/2);

matrixadd(a11, a12, as, n/2);

matrixmulti(as, b22, p5, n/2);

matrixsub(a21, a11, as, n/2);

matrixadd(b11, b12, bs, n/2);

matrixmulti(as, bs, p6, n/2);

matrixsub(a12, a22, as, n/2);

matrixadd(b21, b22, bs, n/2);

matrixmulti(as, bs, p7, n/2);

//計算c的各個分塊

matrixadd(p1, p4, as, n/2);

matrixsub(p7, p5, bs, n/2);

matrixadd(as, bs, c11, n/2);

matrixadd(p3, p5, c12, n/2);

matrixadd(p2, p4, c21, n/2);

matrixadd(p1, p3, as, n/2);

matrixsub(p6, p2, bs, n/2);

matrixadd(as, bs, c22, n/2);

//將小矩陣組合為大矩陣c

for(int i = 0;i < n/2;i++)

for(int j = 0;j < n/2;j++)

//**分配的記憶體空間

for(int i = 0;i < n/2;i++)

delete a11;

delete a12;

delete a21;

delete a22;

delete b11;

delete b12;

delete b21;

delete b22;

delete c11;

delete c12;

delete c21;

delete c22;

delete p1;

delete p2;

delete p3;

delete p4;

delete p5;

delete p6;

delete p7;

delete as;

delete bs;

}}// 測試資料:0~63的8*8矩陣

int main()

int cnt = 0;

for(int i = 0;i < n;i++)

for(int j = 0;j < n;j++)

matrixmulti(a, b, c, n);

for(int i = 0;i < n;i++){

for(int j = 0;j < n;j++){

cout《在c++中,二維矩陣作為函式的形參主要有以下幾種方式:

採用類似一維陣列的方式,但是必須指明第二維的確切大小,適合維度明確的引數,實參為陣列名

int a[3][4]

int a[4]

int (*a)[4]

在函式內訪問陣列元素時,正常訪問即可

二維陣列當成一維陣列訪問,不需要指明第二維的確切大小,實參實際上是二維陣列的首個元素的位置,可以是*a,也可以是a[0]

int *a
在函式內訪問陣列元素時,可以正常訪問,也可以按照以下方式訪問:

*(p+i*col+j)

二維陣列通過二級指標傳遞,不需要指明第二維的確切大小,實參必須是指標,可以是陣列名

int **a
需要注意的是,需要對二級指標進行記憶體的分配與**:

int **a;

a = new int*[row];

for(int i = 0;i < row;i++)

a[i] = new int[col];

for(int i = 0;i < row;i++)

delete a[i];

delete a;

此外還有什麼強制型別轉換的方法,沒看懂,這裡不整理了。

當然了,沒有維度限制的二維矩陣相乘還可以使用vector。

Strassen s 矩陣乘法 分治法實現

內容會持續更新,有錯誤的地方歡迎指正,謝謝 題目 1.比較數學定義的矩陣乘法演算法和strassen s 矩陣乘法演算法的效率 2.自主生成兩個16 16的矩陣,輸出strassen s 矩陣乘法演算法結果。數學定義的矩陣乘法演算法 利用三個for迴圈來解決,時間複雜度為o n 3 數學定義的矩陣乘...

大整數乘法 分治法

import sys def add n1,n2 字串加法 n1 n1 1 n2 n2 1 補齊到和的最大位數 相加後可能在最後進一位,所以末尾補乙個0 if len n1 1 and sum 0 0 sum sum 1 return sum def muti x1,x2 xi 123435 5 分...

矩陣相乘(分治法)

乙個簡單的分治演算法求矩陣相乘 c a b 假設三個矩陣均為n n,n為2的冪。可以對其分解為4個n 2 n 2的子矩陣分別遞迴求解 遞迴分治演算法 演算法中乙個重要的細節就是在分塊的時候,採用的是下標的方式。include include define row 16 指定 行數 define co...