矩阵相乘(分治法)

2024-06-21 06:58
文章标签 相乘 矩阵 分治

本文主要是介绍矩阵相乘(分治法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一个简单的分治算法求矩阵相乘
C=A * B ,假设三个矩阵均为n×n,n为2的幂。可以对其分解为4个n/2×n/2的子矩阵分别递归求解:
1
2

递归分治算法:
3

算法中一个重要的细节就是在分块的时候,采用的是下标的方式。

#include <stdio.h>
#include <stdlib.h>
#define ROW 16       //指定 行数
#define COL 16       //指定 列数 int a[ROW][COL],b[ROW][COL];  //矩阵a 和 矩阵b
int **c;                      // c = a * b //保存一个矩阵的第一个元素的位置,即左上角元素的下标
//如果加上一个长度就可以知道整个矩阵了
typedef struct {   //这里没有指定一个矩阵的长度,在分块时应该加入长度,否则不知道子块矩阵的大小int str,stc;    //str行下标  ; strc列下标
}subarr;// 两矩阵arr、brr相加减 保存在temp中
void operate(int **arr,int **brr,subarr te,char op,int **temp,int len);//分治法 求矩阵相乘 ,sa,sb分别为矩阵a,b参加运算的首元素
int ** square_recursive(subarr sa,subarr sb,subarr sc,int len){int n=len;int **temp;int i;// 申请一个临时矩阵,用于保存a*b temp=(int**)malloc(sizeof(int *)*n);for ( i=0;i<n;++i){temp[i]=(int *)malloc(sizeof(int)*n);}// 长度为1 则直接相乘if (n==1){temp[0][0]=a[sa.str][sa.stc]*b[sb.str][sb.stc];}else{// 这里都是对下标进行初始化// sa,sb,sc代表输入矩阵A,B,temp参加运算的首元素下标,因为进行分块后只进行特定子块的运算//标号1,2,3,4 分别代表第一、二、三、四个子块subarr sa1,sb1, sc1;subarr sa2,sb2, sc2;subarr sa3, sb3,sc3;subarr sa4, sb4, sc4;// 矩阵A 进行分块后的各个子块下标sa1.str=sa.str;sa1.stc=sa.stc;sa2.str=sa.str;sa2.stc=sa.stc+n/2;sa3.stc=sa.stc;sa3.str=sa.str+n/2;sa4.str=sa.str+n/2;sa4.stc=sa.stc+n/2;// 矩阵B 进行分块后的各个子块下标sb1.str=sb.str;sb1.stc=sb.stc;sb2.str=sb.str;sb2.stc=sb.stc+n/2;sb3.stc=sb.stc;sb3.str=sb.str+n/2;sb4.str=sb.str+n/2;sb4.stc=sb.stc+n/2;// 矩阵temp 进行分块后的各个子块下标sc1.str=sc1.stc=0;sc2.str=0;sc2.stc=n/2;sc3.stc=0;sc3.str=n/2;sc4.str=n/2;sc4.stc=n/2;
// 将矩阵分为四块  分别求解。采用下标的方式进行分块,可以省去复制矩阵所产生的时间
// 若要复制矩阵则会产生 O(n*n)的时间复杂度operate(square_recursive(sa1,sb1,sc1,n/2),square_recursive(sa2,sb3,sc1,n/2),sc1,'+',temp,n/2);operate(square_recursive(sa1,sb2,sc2,n/2),square_recursive(sa2,sb4,sc2,n/2),sc2,'+',temp,n/2);operate(square_recursive(sa3,sb1,sc3,n/2),square_recursive(sa4,sb3,sc3,n/2),sc3,'+',temp,n/2);operate(square_recursive(sa3,sb2,sc4,n/2),square_recursive(sa4,sb4,sc4,n/2),sc4,'+',temp,n/2);}return temp;}
//  temp矩阵的te位置(四个子块中的一个)=arr+brr
// len表示arr,brr参加运算的长度
// op是运算符 ‘+’ 
void operate(int **arr,int **brr,subarr te,char op,int **temp,int len){int i,j;switch(op){case '+':for (i=0;i<len;++i){for (j = 0; j < len; ++j){temp[te.str+i][te.stc+j]=arr[i][j]+brr[i][j];}}break;case '-':for (i=0;i<len;++i){for (j = 0; j < len; ++j){temp[te.str+i][te.stc+j]=arr[i][j]-brr[i][j];}}break;}
}
//为矩阵初始化 即赋值
void createarr(int temp[][COL]){int i,j;for (i = 0; i < ROW; ++i){for (j = 0; j < COL; ++j){temp[i][j]=(int)rand()%5;}}}
// 打印C矩阵
void print(){int i,j;printf("\n====================================\n");for (i = 0; i < ROW; ++i){for (j = 0; j < COL; ++j){printf("%d\t", c[i][j]);}printf("\n");}printf("===================================\n");
}
// 打印矩阵
void printarray(int a[ROW][COL]){int i,j;printf("-----------------------\n");for (i = 0; i < ROW; ++i){for (j = 0; j < COL; ++j){printf("%d \t", a[i][j]);}printf("\n");}printf("-----------------------\n");
}int main(){int i,j;subarr sa,sb,sc;int len;//初始化各个下标sa.str=sa.stc=0;sb.str=sb.stc=0;sc.str=sc.stc=0;// 长度赋值,因为在subarr结构里没有长度的定义len=ROW;//申请空间c=(int**)malloc(sizeof(int *)*len);for (i=0;i<len;++i){c[i]=(int *)malloc(sizeof(int)*len);}// 给矩阵A,B 复制初始化createarr(a);createarr(b);//  进行运算c=square_recursive(sa,sb,sc,len);// 打印矩阵A,B,Cprintarray(a);printarray(b);print();return 0;
}

=========== 王杰 原创作品转载请注明出处==============

这篇关于矩阵相乘(分治法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1080511

相关文章

推荐算法之矩阵分解实例

矩阵分解的数据利用的上篇文章的数据,协同过滤 用到的知识 python的surprise k折交叉验证 SVD SVDpp NMF 算法与结果可视化 # 可以使用上面提到的各种推荐系统算法from surprise import SVD,SVDpp,NMFfrom surprise import Datasetfrom surprise import print_perf

江协科技51单片机学习- p16 矩阵键盘

🚀write in front🚀   🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​  💬本系列哔哩哔哩江科大51单片机的视频为主以及自己的总结梳理📚  前言: 本文是根据哔哩哔哩网站上“江协科技51单片机”视频的学习笔记,在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习

使用matlab的大坑,复数向量转置!!!!!变量区“转置变量“功能(共轭转置)、矩阵转置(默认也是共轭转置)、点转置

近期用verilog去做FFT相关的项目,需要用到matlab进行仿真然后和verilog出来的结果来做对比,然后计算误差。近期使用matlab犯了一个错误,极大的拖慢了项目进展,给我人都整emo了,因为怎么做仿真结果都不对,还好整体的代码都是我来写的,慢慢往下找就找到了问题的来源,全网没有看到多少人把这个愚蠢的错误写出来,我来引入一下。 代码错误的表现:复数向量的虚部被取反,正数变成负数,负数

「学转录组入门生信」第二周来获取表达量矩阵

我们第二周目标有四个: 整理数据RNA-seq格式了解数据质控数据比对read定量 首先,我们得要知道我们在转录组分析过程中会遇到很多格式,建议先通过搜索查找了解这些格式是什么 fasta/fas/fagtf/gffbedsam/bamcsv/tsv/txt 接着,我们会在分析过程中时刻检查我们的数据质量,所以你要尝试回答下面这几个问题 数据质控要在哪个阶段做不同阶段要看什么标准质控有哪

「单细胞转录组系列」如何从稀疏矩阵中提取部分数据进行分析

这一篇文章是回答知识星球中一位星友的提问,她的电脑内存有限,无法直接使用所有数据,只能分析部分数据。 数据来源: https://content.cruk.cam.ac.uk/jmlab/atlas_data.tar.gz 解压缩之后,得到下面数据 数据清单 其中raw_counts.mtx是以稀疏矩阵格式存放的表达量数据,文件为6.5G, 用普通的文本编辑器无法打开,

分治精炼宝库----归并排序应用( ´◔︎ ‸◔︎`)

目录 一.基本概念: 二.归并排序:  三.交易逆序对总数:  四.计算右侧小于当前元素的个数: 五.翻转对:  六.合并k个有序链表: 一.基本概念: 🐻在计算机科学中,分治法是一种很重要的算法。字面上的解释就是“分而治之”,就是把一个复杂的问题分成两个或则更多个相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的

最大子数组问题(第4章:分治策略)

求子数组的最大和 题目描述: 输入一个整形数组,数组里有正数也有负数。 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。 求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18。   思路 1 当我们加上一个正数时,和会

Strassen矩阵乘法简要解析(第4章:分治策略)

Strassen矩阵乘法简要解析 Strassen矩阵乘法具体描述如下: 两个n×n 阶的矩阵A与B的乘积是另一个n×n 阶矩阵C,C可表示为假如每一个C(i, j) 都用此公式计算,则计算C所需要的操作次数为n3 m+n2 (n- 1) a,其中m表示一次乘法,a 表示一次加法或减法。 为了使讨论简便,假设n 是2的幂(也就是说, n是1,2,4,8,1 6,...)。 首先,假设

[leetcode] 43. Multiply Strings(大数相乘)

Multiply Strings 描述 Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2. Note: 1. The length of both num1 and num2 is < 110. 2. Both num1 an

leetcode 二分查找·系统掌握 搜索二维矩阵

题目: 题解: 一个可行的思路是使用~01~泛型对每一行的最后一个元素进行查找找到第一个大于等于target的那一行,判断查找结果如果“失败”返回false否则继续在改行进行常规二分查找target的值根据查找结果返回即可。 bool searchMatrix(vector<vector<int>>& matrix, int target) {int l=0,r=matrix.size()-