Java实现矩阵相乘问题
1 问题描述
1.1实验题目
设M1和M2是两个n×n的矩阵,设计算法计算M1×M2 的乘积。
1.2实验目的
(1)提高应用蛮力法设计算法的技能;
(2)深刻理解并掌握分治法的设计思想;
(3)理解这样一个观点:用蛮力法设计的算法,一般来说,经过适度的努力后,都可以对其进行改进,以提高算法的效率。
1.3实验要求
(1)设计并实现用BF(Brute-Force,即蛮力法)方法求解矩阵相乘问题的算法;
(2)设计并实现用DAC(Divide-And-Conquer,即分治法)方法求解矩阵相乘问题的算法;
(3)以上两种算法的输入既可以手动输入,也可以自动生成;
(4)对上述两个算法进行时间复杂性分析,并设计实验程序验证分析结果;
(5)设计可供用户选择算法的交互式菜单(放在相应的主菜单下)。
2 解决方案
2.1 分治法原理简述
分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。
如果原问题可分割成k个子问题,1<k≤n ,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
分治法所能解决的问题一般具有以下几个特征:
该问题的规模缩小到一定的程度就可以容易地解决
该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
利用该问题分解出的子问题的解可以合并为该问题的解;
该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
2.2 分治法求解矩阵相乘原理
首先了解一下传统计算矩阵相乘的原理:
其次,看一下优化后的矩阵相乘法原理:
最后,看一下本文利用分治法求解矩阵相乘的原理(PS:本文求解其效率不是最高,主要是体验一下分治法,重点在于分治法):
注意:使用分治法求解两个nxn阶矩阵相乘,其中n值为2的幂值,否则只能使用蛮力法计算。
本文具体源码主要根据以上分块矩阵方法,先分块(即使用分治法),然后递归求解。
2.3 具体实现源码
package com.liuzhen.dac;
public class Matrix {
//初始化一个随机nxn阶矩阵
public static int[][] initializationMatrix(int n){
int[][] result = new int[n][n];
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
result[i][j] = (int)(Math.random()*10); //采用随机函数随机生成1~10之间的数
}
}
return result;
}
//蛮力法求解两个nxn和nxn阶矩阵相乘
public static int[][] BruteForce(int[][] p,int[][] q,int n){
int[][] result = new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
result[i][j] = 0;
for(int k=0;k<n;k++){
result[i][j] += p[i][k]*q[k][j];
}
}
}
return result;
}
//分治法求解两个nxn和nxn阶矩阵相乘
public static int[][] DivideAndConquer(int[][] p,int[][] q,int n){
int[][] result = new int[n][n];
//当n为2时,返回矩阵相乘结果
if(n == 2){
result = BruteForce(p,q,n);
return result;
}
//当n大于3时,采用采用分治法,递归求最终结果
if(n > 2){
int m = n/2;
int[][] p1 = QuarterMatrix(p,n,1);
int[][] p2 = QuarterMatrix(p,n,2);
int[][] p3 = QuarterMatrix(p,n,3);
int[][] p4 = QuarterMatrix(p,n,4);
// System.out.println();
// System.out.print("矩阵p1值为:");
// PrintfMatrix(p1,m);
// System.out.println();
// System.out.print("矩阵p2值为:");
// PrintfMatrix(p2,m);
// System.out.println();
// System.out.print("矩阵p3值为:");
// PrintfMatrix(p3,m);
// System.out.println();
// System.out.print("矩阵p4值为:");
// PrintfMatrix(p4,m);
int[][] q1 = QuarterMatrix(q,n,1);
int[][] q2 = QuarterMatrix(q,n,2);
int[][] q3 = QuarterMatrix(q,n,3);
int[][] q4 = QuarterMatrix(q,n,4);
int[][] result1 = QuarterMatrix(result,n,1);
int[][] result2 = QuarterMatrix(result,n,2);
int[][] result3 = QuarterMatrix(result,n,3);
int[][] result4 = QuarterMatrix(result,n,4);
result1 = AddMatrix(DivideAndConquer(p1,q1,m),DivideAndConquer(p2,q3,m),m);
result2 = AddMatrix(DivideAndConquer(p1,q2,m),DivideAndConquer(p2,q4,m),m);
result3 = AddMatrix(DivideAndConquer(p3,q1,m),DivideAndConquer(p4,q3,m),m);
result4 = AddMatrix(DivideAndConquer(p3,q2,m),DivideAndConquer(p4,q4,m),m);
result = TogetherMatrix(result1,result2,result3,result4,m);
}
return result;
}
//获取矩阵的四分之一,并决定返回哪一个四分之一
public static int[][] QuarterMatrix(int[][] p,int n,int number){
int rows = n/2; //行数减半
int cols = n/2; //列数减半
int[][] result = new int[rows][cols];
switch(number){
case 1 :
{
// result = new int[rows][cols];
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
result[i][j] = p[i][j];
}
}
break;
}
case 2 :
{
// result = new int[rows][n-cols];
for(int i=0;i<rows;i++){
for(int j=0;j<n-cols;j++){
result[i][j] = p[i][j+cols];
}
}
break;
}
case 3 :
{
// result = new int[n-rows][cols];
for(int i=0;i<n-rows;i++){
for(int j=0;j<cols;j++){
result[i][j] = p[i+rows][j];
}
}
break;
}
case 4 :
{
// result = new int[n-rows][n-cols];
for(int i=0;i<n-rows;i++){
for(int j=0;j<n-cols;j++){
result[i][j] = p[i+rows][j+cols];
}
}
break;
}
default:
break;
}
return result;
}
//把均分为四分之一的矩阵,聚合成一个矩阵,其中矩阵a,b,c,d分别对应原完整矩阵的四分中1、2、3、4
public static int[][] TogetherMatrix(int[][] a,int[][] b,int[][] c,int[][] d,int n){
int[][] result = new int[2*n][2*n];
for(int i=0;i<2*n;i++){
for(int j=0;j<2*n;j++){
if(i<n){
if(j<n){
result[i][j] = a[i][j];
}
else
result[i][j] = b[i][j-n];
}
else{
if(j<n){
result[i][j] = c[i-n][j];
}
else{
result[i][j] = d[i-n][j-n];
}
}
}
}
return result;
}
//求两个矩阵相加结果
public static int[][] AddMatrix(int[][] p,int[][] q,int n){
int[][] result = new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
result[i][j] = p[i][j]+q[i][j];
}
}
return result;
}
//控制台输出矩阵
public static void PrintfMatrix(int[][] matrix,int n){
for(int i=0;i<n;i++){
System.out.println();
for(int j=0;j<n;j++){
System.out.print("\t");
System.out.print(matrix[i][j]);
}
}
}
public static void main(String args[]){
int[][] p = initializationMatrix(8);
int[][] q = initializationMatrix(8);
System.out.print("矩阵p初始化值为:");
PrintfMatrix(p,8);
System.out.println();
System.out.print("矩阵q初始化值为:");
PrintfMatrix(q,8);
int[][] bf_result = BruteForce(p,q,8);
System.out.println();
System.out.print("蛮力法计算矩阵p*q结果为:");
PrintfMatrix(bf_result,8);
int[][] dac_result = DivideAndConquer(p,q,8);
System.out.println();
System.out.print("分治法计算矩阵p*q结果为:");
PrintfMatrix(dac_result,8);
}
}
2.4 运算结果截图
Java实现矩阵相乘问题的更多相关文章
- java 写一个 map reduce 矩阵相乘的案例
1.写一个工具类用来生成 map reduce 实验 所需 input 文件 下面两个是原始文件 matrix1.txt 1 2 -2 0 3 3 4 -3 -2 0 2 3 5 3 -1 2 -4 ...
- Java实现 蓝桥杯 算法提高 矩阵相乘
算法提高 矩阵相乘 时间限制:1.0s 内存限制:256.0MB 问题描述 小明最近在为线性代数而头疼,线性代数确实很抽象(也很无聊),可惜他的老师正在讲这矩阵乘法这一段内容. 当然,小明上课打瞌睡也 ...
- Java实验项目四——多线程矩阵相乘算法的设计
Program:多线程矩阵相乘算法的设计 Description:利用多线程实现矩阵相乘,因为各个线程的运算互不影响, 所以不用使用锁,代码如下: thread.OperateMatrix类,实现矩阵 ...
- MapReduce实现矩阵相乘
矩阵相乘能够查看百度百科的解释http://baike.baidu.com/view/2455255.htm?fr=aladdin 有a和b两个矩阵 a: 1 2 ...
- HDU1575Tr A(矩阵相乘与快速幂)
Tr A hdu1575 就是一个快速幂的应用: 只要知道怎么求矩阵相乘!!(比赛就知道会超时,就是没想到快速幂!!!) #include<iostream> #include<st ...
- <矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置>
//矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置 #include<stdio.h> #include<stdlib.h> #define M 2 #define N 3 #d ...
- 利用Hadoop实现超大矩阵相乘之我见(二)
前文 在<利用Hadoop实现超大矩阵相乘之我见(一)>中我们所介绍的方法有着“计算过程中文件占用存储空间大”这个缺陷,本文中我们着重解决这个问题. 矩阵相乘计算思想 传统的矩阵相乘方法为 ...
- 利用Hadoop实现超大矩阵相乘之我见(一)
前记 最近,公司一位挺优秀的总务离职,欢送宴上,她对我说“你是一位挺优秀的程序员”,刚说完,立马道歉说“对不起,我说你是程序员是不是侮辱你了?”我挺诧异,程序员现在是很低端,很被人瞧不起的工作吗?或许 ...
- java 简单矩阵乘法运算
1.计算的两个矩阵其中第一个矩阵的列数必须和第二个矩阵的行数一致(或者反过来): 2.第一个矩阵的行数决定了结果矩阵的行数,第二个矩阵的列数决定了结果矩阵的列数: package org.admln. ...
随机推荐
- [hdu4622 Reincarnation]后缀数组
题意:给一个长度为2000的字符串,10000次询问区间[L,R]内的不同子串的个数 思路:对原串的每个前缀求一边后缀数组,询问[L,R]就变成了询问[L,n]了,即求一个后缀里面出现了多少个不同子串 ...
- C# 数据操作系列 - 5. EF Core 入门
0.前言 上一章简单介绍了一下ORM框架,并手写了一个类似ORM的工具类.这一章将介绍一个在C#世界里大名鼎鼎的ORM框架--Entity Framework的Core版. Entity Framew ...
- ASA failover配置(A/S)
环境描述 1. 两条公网出口,分别为移动,联通 2. 两台ASA做主备配置,实现出口故障转移 3. 内网两台核心做堆叠配置(由于模拟器无法实现堆叠,此处使用HSRP) 需求描述 1. 当一条公网链路故 ...
- Python --函数学习1
函数 -函数是代码的一种组织形式 -函数应该能完成一项特定的工作,而且一般一个函数完成一项工作 -函数的使用: 函数使用需要先定义 使用函数,俗称调用 pps:1.只是定义的话不会执行 2.def关键 ...
- 【雕爷学编程】Arduino动手做(59)---RS232转TTL串口模块
37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的.鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为 ...
- WebApiClient性能参考
1 文章目的 昨天写了走进WebApiClientCore的设计,介绍了WebApiClient的变化与设计之后,收到大家支持的.赞许的,还有好的建议和顾虑,比如WebApiClient性能怎么样,有 ...
- php RSA和AES加密算法
一.RSA加密 RSA只说PHP中的应用,详细的算法原理解释,请自行百度,或者参考(RSA加密算法-详细解释以及公钥加密为什么每次都不一样) 总结:公钥加密.私钥解密.私钥签名.公钥验签. 注意: 1 ...
- 【Java】手把手模拟CAS,瞬间理解CAS的机制
话不多少,先看个案例,[模拟100个用户,每个用户访问10次网站]”: public class ThreadDemo1 { //总访问量 ; //模拟访问的方法 public static void ...
- 【网络安全】【02】Windows系统如何屏蔽自动更新
一.win键 + r ==> 输入 services.msc 二. win键 + r ==> 输入 gpedit.msc PS:我的电脑基本两年没有更新过了 -_-
- Poj 2109 k^n = p.
Poj2109(1)和Poj2109(2)这两种解答都是有漏洞的,就是解不一定存在. 当然这种漏洞的存在取决于出题人是否假设输入的n,p必须默认有kn = p这样的关系存在. 这道题可以详细看http ...