一、啥是传递闭包?
概念:
“传递闭包、即在数学中,在集合X上的二元关系R的传递闭包是包含R的X上的最小的传递关系。” ——《百度百科》
人话 :
建立传递闭包的过程,就是给定一个有向(无向)图,对于节点 i 和节点 j ,如果他们联通但不直接相连,我们就建一个 i 到 j 的边.
二、求解算法
矩阵相乘累加关系幂算法
Warshall算法
Floyd算法
此算法代码过于简单,可是想到却不容易。建议通过传递关系的概念手动模拟。
三、话不多说直接上代码
//实现内容:
//矩阵输入输出、矩阵求幂、矩阵相乘、warshall算法求传递闭包
#include <iostream>
#include <vector>//此举原意在测试两算法时间复杂度时创建高阶矩阵
#define max 10 //定义常量 const int 亦可
using namespace std;
//创建矩阵类
class Matrix{
private:
int steps;//矩阵阶
bool matrix[max][max];//原关系矩阵
bool result2[max][max];//关系矩阵二次幂
bool result3[max][max];//关系矩阵三次幂
bool LastResult[max][max];//用以保存结果
public:
Matrix();//construstor
Matrix(int steps);
void get_steps();//用以手动输入阶数
void input_matrix();//用以从键盘输入矩阵
void output_matrix();//用以输出LastResult[][]
void mult_matrix();//关系矩阵相乘累加以实现求解
void warshall();//沃舍尔算法实现
};
Matrix::Matrix()
{
steps=max;
}
Matrix::Matrix(int steps)
{
steps=steps;
}
void Matrix::get_steps()
{
cout<<"请输入矩阵的阶数"<<endl;
int n;
cin>>n;
steps=n;
}
void Matrix::input_matrix()
{
cout<<"请输入矩阵: "<<endl;
for(int i=0;i<steps;i++)
for(int j=0;j<steps;j++)
cin>>matrix[i][j];
cout<<"您输入的矩阵为:"<<endl;
for(int i=0;i<steps;i++)
{
cout<<endl;
for(int j=0;j<steps;j++)
cout<<matrix[i][j]<<" ";
}
cout<<endl;
}
void Matrix::mult_matrix()
{
//以下两个三层for循环可使用中间变量保存result2[][]
//在此基础上得出result3[][]=result2[][]*matrix[][] 可减少代码膨胀
for(int i=0;i<steps;i++)
{
for(int j=0;j<steps;j++)
{
bool sum=0;
for(int k=0;k<steps;k++)
{
sum+=(matrix[i][k]*matrix[k][j]);
}
result2[i][j]=sum;
}
}
if(steps>=3)
for(int i=0;i<steps;i++)
{
for(int j=0;j<steps;j++)
{
bool sum=0;
for(int k=0;k<steps;k++)
{
sum+=(result2[i][k]*matrix[k][j]);
}
result3[i][j]=sum;
}
}
for(int i=0;i<steps;i++)
{
for (int j=0;j<steps;j++)
{
if(steps==1) LastResult[i][j]=matrix[i][j];//这句几乎是不需要的,一阶矩阵即一个数
else if(steps==2) LastResult[i][j]=matrix[i][j]+result2[i][j];
else if(steps>=3) LastResult[i][j]=matrix[i][j]+result2[i][j]+result3[i][j];
}
}
}
//沃舍尔算法,具体解析见教材或csdn
void Matrix::warshall()
{
for(int k=0;k<steps;k++)
for(int i=0;i<steps;i++)
for(int j=0;j<steps;j++)
{
if(matrix[i][k]==1&&matrix[k][j]==1)
LastResult[i][j]=1;
}
}
//输出函数
void Matrix::output_matrix()
{
for(int i=0;i<steps;i++){
for(int j=0;j<steps;j++)
cout<<LastResult[i][j]<<" ";
cout<<endl;
}
}
//主函数
int main(){
Matrix M(4);
M.get_steps();
M.input_matrix();
M.mult_matrix();
cout<<"矩阵相乘算法得出的关系矩阵:"<<endl;
M.output_matrix();
M.warshall();
cout<<"warshall算法得出的关系矩阵:"<<endl;
M.output_matrix();
return 0;
}
c++运行结果
四、jiva实现及算法时间复杂度比较
下面给出寝室大佬(其实是个撒币)的完整代码,说实话整挺好。
import java.util.Random;
import java.util.Scanner;
public class LiSan {
public static void main(String[] args) {
Random r = new Random(1);
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
Warshall Wa=new Warshall(n);
Matrix_Multi_Sum Ma=new Matrix_Multi_Sum(n);
for(int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
int x=sc.nextInt();
Wa.setMatrix(i,j,x);
Ma.setMatrix(i,j,x);
}
}
System.out.println();
long startTime11=System.nanoTime(); //获取开始时间
Ma.set_Matrix_Multi_Sum();
long endTime11=System.nanoTime(); //获取结束时间
System.out.println("关系矩阵相乘运行时间: "+(endTime11-startTime11)+"ns");
long startTime22=System.nanoTime(); //获取开始时间
Wa.setWarshall();
long endTime22=System.nanoTime(); //获取结束时间
System.out.println("Warshall运行时间: "+(endTime22-startTime22)+"ns");
System.out.println(n+"阶关系矩阵Warshall算法比关系矩阵相乘算法快"+((endTime11-
startTime11)/(endTime22-startTime22))+"倍");
Wa.showWarshall();
System.out.println();
Ma.show_Matrix();
System.out.println();
System.out.println("判断两种算法得到的关系矩阵是否相同:"+Wa.Is_equal(Ma));
for(int t=10;t<=300;t+=10) {
Warshall Wa_Auto=new Warshall(t);
Matrix_Multi_Sum Ma_Auto=new Matrix_Multi_Sum(t);
for (int i = 1; i <=t; i++) {
for (int j = 1; j <= t; j++) {
int x1 = r.nextInt(2);
Wa_Auto.setMatrix(i, j, x1);
Ma_Auto.setMatrix(i, j, x1);
}
}
System.out.println();
startTime11 = System.nanoTime(); //获取开始时间
Ma_Auto.set_Matrix_Multi_Sum();
endTime11 = System.nanoTime(); //获取结束时间
System.out.println("关系矩阵相乘运行时间:" + (endTime11 - startTime11)
+ "ns");
startTime22 = System.nanoTime(); //获取开始时间
Wa_Auto.setWarshall();
endTime22 = System.nanoTime(); //获取结束时间
System.out.println("Warshall运行时间: " + (endTime22 - startTime22) +
"ns");
System.out.println(t + "阶关系矩阵Warshall算法比关系矩阵相乘算法快" +
((endTime11 - startTime11) / (endTime22 - startTime22)) + "倍");
System.out.println("判断两种算法得到的关系矩阵是否相同:true" );
}
}
}
class Warshall{
int [][]Matrix=new int[1001][1001];
int n;
Warshall(int n){
this.n=n;
}
void setMatrix(int i,int j,int x)
{
Matrix[i][j]=x;
}
void setWarshall()
{
for (int i = 1;i<=n; i++)
{
for (int j = 1;j<=n; j++)
{
for(int k=1;k<=n;k++)
{
if(Matrix[j][i]==1&&Matrix[i][k]==1)
Matrix[j][k]=1;
}
}
}
}
void showWarshall()
{
for (int i = 1;i<=n; i++)
{
for (int j = 1;j<=n; j++)
{
System.out.print(Matrix[i][j]+" ");
}
System.out.println();
}
}
boolean Is_equal(Matrix_Multi_Sum Ma){
boolean Is=true;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if (this.Matrix[i][j] != Ma.Matrix_sum[i][j]) {
Is = false;
break;
}
}
}
return Is;
}
}
class Matrix_Multi_Sum{
int [][]Matrix=new int[1001][1001];
int [][]Matrix_double=new int[1001][1001];
int [][]Matrix_sum=new int[1001][1001];
int [][]Matrix_odd=new int[1001][1001];
int [][]Matrix_even=new int[1001][1001];
int n;
Matrix_Multi_Sum(int n){
this.n=n;
}
void setMatrix(int i,int j,int x)
{
Matrix[i][j]=x;
}
void set_Matrix_Multi_Sum()
{
for(int m=1;m<=n;m++)
{
if(m==2)
{
Matrix_square();
}
else if(m%2==1&&m!=1)
{
Matrix_Odd();
}
else if((m & 1) == 0)
{
Matrix_Odd();
Matrix_Even(Matrix_odd, Matrix_even);
}
for(int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
if(m==1) Matrix_sum[i][j]+=Matrix[i][j];
else if(m==2) Matrix_sum[i][j]+=Matrix_double[i][j];
else if((m&1)==1)Matrix_sum[i][j]+=Matrix_odd[i][j];
else if((m&1)==0)Matrix_sum[i][j]+=Matrix_even[i][j];
}
}
}
}
private void Matrix_Even(int[][] matrix_odd, int[][] matrix_even) {
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int sum=0;
for(int k=1;k<=n;k++)
{
sum+=(matrix_odd[i][k]*Matrix[k][j]);
}
matrix_even[i][j]=sum;
}
}
}
private void Matrix_Odd() {
Matrix_square();
Matrix_Even(Matrix_double, Matrix_odd);
}
private void Matrix_square() {
Matrix_Even(Matrix, Matrix_double);
}
void show_Matrix()
{
for (int i = 1;i<=n; i++)
{
for (int j = 1;j<=n; j++)
{
if(Matrix_sum[i][j]>1)Matrix_sum[i][j]=1;
System.out.print(Matrix_sum[i][j]+" ");
}
System.out.println();
}
}
boolean Is_equal(Matrix_Multi_Sum Wa){
boolean Is=true;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if (this.Matrix[i][j] != Wa.Matrix_sum[i][j]) {
Is = false;
break;
}
}
}
return Is;
}
}
java运行结果
总结
通过不同算法运行时间的比较,可见一个好的算法是多么的重要啊啊啊。
如需完整版c++实验报告请评论告知。
还请路过的大佬们评价指点。