矩阵相乘简单递归实现by24k
算法导论课后习题要求写一个最简单的2的n此方的矩阵相乘算法:
本代码测试环境为win10下的VC6.0,目前仅能计算2的n此方的方阵且A,B方阵的阶数必须相同。实际上源码仅能计算两个4*4阶矩阵相乘,想要计算2*2或8*8或16*16等等的矩阵需要手工调整几个参数,但这并不妨碍表现递归算法到C语言的转化核心--如何计算正确的坐标
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define M1 (p1->w-p1->x+1) 4 #define N1 (p1->z-p1->y+1) 5 #define M2 (p2->w-p2->x+1) 6 #define N2 (p2->z-p2->y+1) 7 typedef struct m 8 { 9 int x,y,w,z;//左上角坐标(x,y)右下角坐标(w,z);确定数组大小,为实际坐标 10 }M; 11 typedef struct ret 12 { 13 int c[4][4]; 14 }R; 15 R *Matrix_Multiply(M *p1,M *p2,int A[][4],int B[][4]) 16 { 17 int i,j,l=0,k=0; 18 R *r=(R*)malloc(sizeof(R)); 19 r->c[0][0]=0; 20 R *r1[8]; 21 for(l=0;l<8;l++) 22 r1[l]=(R*)malloc(sizeof(R)); 23 M *m1,*m2; 24 m1=m2=NULL; 25 m1=(M*)malloc(sizeof(M)); 26 m2=(M*)malloc(sizeof(M)); 27 if(M1==1&&N1==1&&M2==1&&N2==1) 28 { 29 r->c[0][0]=A[p1->x][p1->y]*B[p2->x][p2->y]; 30 return r; 31 } 32 else 33 { 34 ///////////////c11=a11*b11+a12*b21////////////// 35 //a11 36 m1->x=p1->x; 37 m1->y=p1->y; 38 m1->w=p1->x+M1/2-1; 39 m1->z=p1->y+N1/2-1; 40 //b11 41 m2->x=p2->x; 42 m2->y=p2->y; 43 m2->w=p2->x+M2/2-1; 44 m2->z=p2->y+N2/2-1; 45 46 r1[0]=Matrix_Multiply(m1,m2,A,B); 47 48 //a12 49 m1->x=p1->x; 50 m1->y=p1->y+N1/2; 51 m1->w=p1->x+M1/2-1; 52 m1->z=p1->y+N1-1; 53 54 //b21 55 m2->x=p2->x+M2/2; 56 m2->y=p2->y; 57 m2->w=p2->x+M2-1; 58 m2->z=p2->y+N2/2-1; 59 60 r1[1]=Matrix_Multiply(m1,m2,A,B); 61 ///sum a11*b11 and a12*b21 62 for(i=0;i<M1/2;i++) 63 for(j=0;j<N2/2;j++) 64 { 65 r->c[i][j]=r1[0]->c[i][j]+r1[1]->c[i][j]; 66 } 67 ////////////c12=a11*b12+a12*b22//// 68 //a11 69 m1->x=p1->x; 70 m1->y=p1->y; 71 m1->w=p1->x+M1/2-1; 72 m1->z=p1->y+N1/2-1; 73 74 //b12 75 m2->x=p2->x; 76 m2->y=p2->y+N2/2; 77 m2->w=p2->x+M2/2-1; 78 m2->z=p2->y+N2-1; 79 80 r1[2]=Matrix_Multiply(m1,m2,A,B); 81 82 //a12 83 m1->x=p1->x; 84 m1->y=p1->y+N1/2; 85 m1->w=p1->x+M1/2-1; 86 m1->z=p1->y+N1-1; 87 //b22 88 m2->x=p2->x+M2/2; 89 m2->y=p2->y+N2/2; 90 m2->w=p2->x+M2-1; 91 m2->z=p2->y+N2-1; 92 r1[3]=Matrix_Multiply(m1,m2,A,B); 93 94 for(i=0;i<M1/2;i++) 95 for(j=0;j<N2/2;j++) 96 { 97 r->c[i][N2/2+j]=r1[2]->c[i][j]+r1[3]->c[i][j]; 98 } 99 ////////////c21=a21*b11+a22*b21////// 100 101 //a21 102 m1->x=p1->x+M1/2; 103 m1->y=p1->y; 104 m1->w=p1->x+M1-1; 105 m1->z=p1->y+N1/2-1; 106 107 //b11 108 m2->x=p2->x; 109 m2->y=p2->y; 110 m2->w=p2->x+M2/2-1; 111 m2->z=p2->y+N2/2-1; 112 113 r1[4]=Matrix_Multiply(m1,m2,A,B); 114 115 //a22 116 m1->x=p1->x+M1/2; 117 m1->y=p1->y+N1/2; 118 m1->w=p1->x+M1-1; 119 m1->z=p1->y+N1-1; 120 //b21 121 m2->x=p2->x+M2/2; 122 m2->y=p2->y; 123 m2->w=p2->x+M2-1; 124 m2->z=p2->y+N2/2-1; 125 126 127 r1[5]=Matrix_Multiply(m1,m2,A,B); 128 129 for(i=0;i<M1/2;i++) 130 for(j=0;j<N2/2;j++) 131 r->c[M1/2+i][j]=r1[4]->c[i][j]+r1[5]->c[i][j]; 132 133 ///////////c22=a21*b12+a22*b22// 134 135 //a21 136 m1->x=p1->x+M1/2; 137 m1->y=p1->y; 138 m1->w=p1->x+M1-1; 139 m1->z=p1->y+N1/2-1; 140 141 //b12 142 m2->x=p2->x; 143 m2->y=p2->y+N2/2; 144 m2->w=p2->x+M2/2-1; 145 m2->z=p2->y+N2-1; 146 147 r1[6]=Matrix_Multiply(m1,m2,A,B); 148 149 //a22 150 m1->x=p1->x+M1/2; 151 m1->y=p1->y+N1/2; 152 m1->w=p1->x+M1-1; 153 m1->z=p1->y+N1-1; 154 155 //b22 156 m2->x=p2->x+M2/2; 157 m2->y=p2->y+N2/2; 158 m2->w=p2->x+M2-1; 159 m2->z=p2->y+N2-1; 160 161 r1[7]=Matrix_Multiply(m1,m2,A,B); 162 163 for(i=0;i<M1/2;i++) 164 for(j=0;j<N2/2;j++) 165 r->c[M1/2+i][N2/2+j]=r1[6]->c[i][j]+r1[7]->c[i][j]; 166 for(i=0;i<8;i++) 167 free(r1[i]); 168 free(m1); 169 free(m2); 170 return r; 171 } 172 } 173 int main() 174 { 175 int A[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},B[4][4]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; 176 R *pr=(R*)malloc(sizeof(R)); 177 M *p1,*p2; 178 p1=(M*)malloc(sizeof(M)); 179 p2=(M*)malloc(sizeof(M)); 180 p1->x=p1->y=p2->x=p2->y=0; 181 p1->w=p1->z=p2->w=p2->z=3; 182 pr=Matrix_Multiply(p1,p2,A,B); 183 184 for(int i=0;i<4;i++) 185 { 186 for(int j=0;j<4;j++) 187 { 188 printf("%4d ",pr->c[i][j]);//右对齐输出 189 } 190 printf("\n"); 191 } 192 free(pr); 193 free(p1); 194 free(p2); 195 return 0; 196 }
计算正确的坐标:左上角实际坐标加上合适的offset(偏移量)
for exmple:我们已知A为M*N的矩阵左上角坐标为(x1,y1),计算一下拆分后的矩阵A12的左上角坐标(A12->x1,A12->y1)和右下角的坐标(A12->x2,A12->y2)
A12->x1=A->x1
A12->y1=A->y1+N/2
A12->x2=A->x1+M/2-1
A12->y2=A->y1+N-1
By Ken W.Black 山东科技大学 2017/11/7
本人学生,这是我第一篇博客,如有错误,敬请斧正,感激不尽