1 设计任务
图的连通性证明及类别判定
2.设计内容
编写matlab代码,该代码需实现的功能模块包括:
① 验证所举实例是否满足图的定义;
② 通过对邻接矩阵的计算、可达性矩阵的求解,输出该图中每个节点的次数、判断图的连通性、求出图中到
长度为n的通路(回路)数目;
③ 若为连通图,进一步判定该图是否为树、欧拉图、能否一笔画出,并输出结果;
3.代码程序设计
3.1程序流程图
程序流程图
3.2数据输入输出
3.2.1输入
用户需要输入图的邻接矩阵。
- 元素集合:用户需提供代数系统的基础元素集合,应是方阵,例如:
。
- 节点之间的距离:用户根据输入的邻接矩阵,在其的基础上输入不超过其维度的数字,列如用户达数计算2和3之间的距离为2就先输入2和3并输入2。
3.2.2输出
完成以上输入后,程序将按照既定流程图进行图论实例枚举,并执行以下七个模块:
- 无向图和有向图的验证:深入探究用户定义的邻接矩阵是否满足有向图与无向图,并记录相应的验证数据和结果。
- 节点次数的判断:根据图的性质,确定其各个结点的次数,并记录相应的验证数据和结果。
- 连通性的判断:在有向图的基础上求出可达性矩阵并根据情况判断图的连通性,并记录相应的验证数据和结果。
- 树的判断:根据树的定义以及所给的邻接矩阵进行判断,并记录相应的验证数据和结果。
- 判断欧拉通路与欧拉回路:根据欧拉通路与欧拉回路定义以及所给的邻接矩阵进行判断,并记录相应的验证数据和结果。
- 节点之间距离:根据输入的两节点以及其距离进行计算,并记录相应的验证数据和结果。
- 结果展示:最后,程序将通过弹窗以直观、优雅的方式展示验证结果。
3.3测试
举例
连通性
1、设一个有向图
节点集
边集
所以各个节点的入次与出次为下表
| A | B | C | D |
入次 | 1 | 1 | 1 | 1 |
出次 | 1 | 1 | 1 | 1 |
解:所以得出其邻接矩阵为
接着为我们计算其可达性矩阵
因为P中除去对角线元素外都为1所以P是强连通图。
无向树
2、设一个无向图G2节点集
边集
所以各个节点的总次数如下表
| A | B | C | D | E |
次数 | 2 | 2 | 2 | 1 | 1 |
解:得出邻接矩阵为
接着为我们计算其可达性矩阵
所以无向图P2是连通图。又因为该无向图中不存在回路所以P2还是一个无向树。
程序运行
先输入一个例子,定义一个邻接矩阵,已知其是无向图
将其代入代码中测试:
系统通过弹窗的形式分别输出满足的性质最终性质判定出与我们事先证明的结果一致。
接着再输入一个有向图的例子,定义一个邻接矩阵
将其代入代码中测试
系统通过弹窗的形式分别输出满足的性质最终性质判定出与我们事先证明的结果一致。
4.代码实现
4.1 主程序
clc
clear
close all
%% ---step1:案例测试输入---%%
% A=[0,1,2;1,0,2;1,1,1];%【举例子(非邻接矩阵:存在至少一个元素不为0或1)】
% A=[0,1;1,0;1,1];%【举例子(非邻接矩阵:输入的不是n×n的矩阵)】
% A=[0,1,1;1,0,1;1,1,0];%【举例子(邻接矩阵为无向图:连通图)】√
% A=[0,1,0;0,0,0;1,1,0];%【举例子(邻接矩阵为有向图:单向连通图)】√
% A=[0,1,1;0,0,0;0,0,0];%【举例子(邻接矩阵为有向图:弱连通图)】√
% A=[0,0,0;0,0,0;1,0,0];%【举例子(邻接矩阵为有向图:非连通图)】√
%% [0,1,0,0,0;1,0,1,0,0;0,1,0,0,0;0,0,0,0,1;0,0,0,1,0]页数129面,验证V_i和V_j的长度为Long的回路(通路)条数
% V_1和V_2的长度为Long=3的回路(通路)条数:2√
%% A=[0,1,0,0,0;1,0,1,1,0;0,1,0,0,1;0,1,0,0,0;0,0,1,0,0]页数135面,验证:邻接矩阵为无向图,为无向树√
%% A=[0,1,0,0,0;1,0,1,1,0;0,1,0,0,1;0,1,0,0,1;0,0,1,1,0]页数135面,验证:邻接矩阵为无向图,不为无向树√
%% A=[0,0,0,0,0,1;0,0,0,0,0,0;0,0,0,0,0,0;0,0,0,0,0,1;0,0,0,0,0,1;0,1,1,0,0,0]页数136面,验证:邻接矩阵为有向图,为有向树√
%% A=[0,0,0,0,1,1;0,0,0,0,0,0;0,0,0,0,0,0;0,0,0,0,0,1;0,0,0,0,0,1;0,1,1,0,0,0]页数136面,验证:邻接矩阵为有向图,不为有向树√
%% A=[0,1,1,1;1,0,1,0;1,1,0,1;1,0,1,0];%【举例子(邻接矩阵为无向图:连通图;无欧拉回路不是欧拉图,具备欧拉通路)】√
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%第1部分:图的判定【是否输入正确的邻接矩阵+图的类型(有向图/无向图)】%%%%%%%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% ---step1:是否输入正确的邻接矩阵-Chunzai(存在性)
%% ---如果(存在一个元素为1为真)或者(输入的不是n×n的矩阵)则表示邻接矩阵输入错误
Chunzai=0;%初始化
while Chunzai==0
A=input('请输入邻接矩阵:');
A_index=(A~=0&A~=1);%1.记录邻接矩阵中不为0,1的值为真
n=size(A,1);%记录邻接矩阵的行
m=size(A,2);%记录邻接矩阵的列
if any(A_index(:)')
Chunzai=0;
disp('邻接矩阵输入错误,请重新输入');
disp('错误原因:存在至少一个元素不为0或1');
elseif n~=m
Chunzai=0 ;
disp('邻接矩阵输入错误,请重新输入');
disp('错误原因:输入的不是n×n的矩阵');
else
Chunzai=1 ;
disp('邻接矩阵输入成功');
end
end
%% ---step2:图的类型(有向图/无向图)
if isequal(A,A')
A_type=0;%记录为邻接矩阵为无向图
disp('邻接矩阵为无向图');
else
A_type=1;%记录为邻接矩阵为有向图
disp('邻接矩阵为有向图');
end
disp(' ')
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%第2部分:邻接矩阵的计算+可达性矩阵的求解%%%%%%%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% ---step1:通过邻接矩阵的计算判断图的每个节点的次数---%%
%% 输入:A_type-邻接矩阵为无向图/有向图,A-邻接矩阵;
%% 输出:Wuxiang_siz-无向图各个节点的总次数;Youxiang_insize-%有向图各个节点的引入次数;Youxiang_outsize-有向图各个节点的引出次数;result_Number_of_nodes-存储所有结果
[Wuxiang_size,Youxiang_insize,Youxiang_outsize,result_Number_of_nodes]=Number_of_nodes(A_type,A);
%% ---step2:可达性矩阵的求解判断图的类型:无向图(连通,非连通);有向图(强连通,单向连通,弱连通,非连通)---%%
%% 输入:A_type-有向图/无向图;A-邻接矩阵
%% 输出:QiangLiangtong-强连通;DanxiangLiantong-单向连通;RuoLiantong-弱连通;YouxiangLiangtong-有向图为连通图;Liangtong_Wu-无向图为连通图
%% 输出:A_ruo--有向图的弱连通邻接矩阵;
[QiangLiangtong,DanxiangLiantong,RuoLiantong,YouxiangLiangtong,WuxiangLiangtong,A_ruo]=Classificztion_of_Connectedgraphs(A_type,A);
disp(' ')
%% ---step3:根据用户输入求V_i和V_j的长度为Long的回路(通路)---%%
V_i=input(['请输入节点i(注意不要超过',num2str(n),'):']);
V_j=input(['请输入节点j(注意不要超过',num2str(m),'):']);
Long=input(['请输入的要求长度(注意不要超过',num2str(n),'):']);
%% 输入:A-邻接矩阵;V_i-输入节点i;V_j-输入节点j;Long-要求长度
%% 输出:Long_res-V_i和V_j的长度为Long的回路(通路)条数
Long_res=Vi_to_Vj_Long_caclulation(A,V_i,V_j,Long);
disp(['从节点',num2str(V_i),'到节点',num2str(V_j),'长度为',num2str(Long),'的通路(回路)条数为:',num2str(Long_res)]);
%% 记录
%result_of_Long-存储所有结果
result_of_Long{1,1}=['从节点',num2str(V_i),'到节点',num2str(V_j),'长度为',num2str(Long),'的通路(回路)条数为:',num2str(Long_res)];
disp(' ')
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%第3部分:树与欧拉图%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% ---step1:树的判定---%%
%% 无向图判断是否为无向树:不包含回路的连通图【1.是连通图;2.不包含回路:对角线为0】
%% 有向图判断是否为有向树:不考虑方向为无向图时为不包含回路的连通图【1.变为无向图;2.是连通图;3.不包含回路:对角线为0】
%% 输入:A-邻接矩阵;A_type-有向图/无向图;WuxiangLiangtong-无向图为连通图;RuoLiantong-弱连通;A_ruo--有向图的弱连通邻接矩阵;
%% 输出:Wuxiang_Tree-无向树判定;Youxiang_Tree-有向树
[Wuxiang_Tree,Youxiang_Tree]=Tree_determination(A,A_type,RuoLiantong,WuxiangLiangtong,A_ruo);
disp(' ')
%% ---step2:无向连通图是否为欧拉图与存在欧拉通路---%%
%% 输入:A_type-有向图/无向图;Wuxiang_siz-无向图各个节点的总次数;Youxiang_insize-%有向图各个节点的引入次数;Youxiang_outsize-有向图各个节点的引出次数
%% 输出:Wuxiang_EularPath-无向欧拉回路判定;Youxiang_EularPath-有向欧拉回路判定; WuxiangPass_path-无向欧拉通路判定;;YouxiangPass_path-有向欧拉通路判定;
%% 输出:OnePrint-一笔画成判定
[Wuxiang_EularPath,Youxiang_EularPath,WuxiangPass_path,YouxiangPass_path,OnePrint]=EularPath_determination(A_type,Wuxiang_size,Youxiang_insize,Youxiang_outsize,YouxiangLiangtong,WuxiangLiangtong);
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%第4部分:弹窗输出%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Pop_up_output(A_type,result_Number_of_nodes,QiangLiangtong,DanxiangLiantong,RuoLiantong,YouxiangLiangtong,WuxiangLiangtong,result_of_Long,Wuxiang_Tree,Youxiang_Tree,Wuxiang_EularPath,Youxiang_EularPath,WuxiangPass_path,YouxiangPass_path,OnePrint)
4.1 子程序
function [QiangLiangtong,DanxiangLiantong,RuoLiantong,YouxiangLiangtong,WuxiangLiangtong,A_ruo]=Classificztion_of_Connectedgraphs(A_type,A)
%% 输入:A_type-有向图/无向图;A-邻接矩阵
%% 输出:QiangLiangtong-强连通;DanxiangLiantong-单向连通;RuoLiantong-弱连通;YouxiangLiangtong-有向图为连通图;Liangtong_Wu-无向图为连通图
%% 输出:A_ruo--有向图的弱连通邻接矩阵;
%% 初始化
QiangLiangtong=0;%初始化强连通为0
DanxiangLiantong=0;%初始化单向连通为0
RuoLiantong=0;%初始化弱连通为0
YouxiangLiangtong=0;%初始化有向图不是连通图为0
WuxiangLiangtong=0;%初始化无向图不是连通图为0
A_ruo=NaN;%初始化有向图的弱连通邻接矩阵不存在
%% 连通图判断
if A_type==1%若为有向图
disp('对于这个有向图');
%% 判定连通图类型:1.强联通P=A(+)A^(2)(+)...(+)A^(n)-除对角线都为1;2.单向联通P'=p(+)p(转置)-除对角线都为1;3.弱联通A'=A(+)A(转置)再求P-除对角线都为1;4.非联通
%% 1.强联通P=A(+)A^(2)(+)...(+)A^(n)-除对角线都为1;
% step1:求P=A(+)A^(2)(+)...(+)A^(n)%(其中括号加为:max(A,B);括号乘为:KuoHaoCheng(A, B))
P_Qiang=KedaJZ_caclulation(A);
% step2:判断除对角线是否都为零:DuijiaoPanduan(P)
disp('1.强连通判定:');
Duijiao_Qiang=DuijiaoPanduan(P_Qiang);
%% 2.单向联通P'=p(+)p(转置)-除对角线都为1;
% step1:P'=p(+)p(转置)
P_dan=max(P_Qiang,P_Qiang');
% step2:判断除对角线是否都为零:DuijiaoPanduan(P)
disp('2.单向连通判定:');
Duijiao_dan=DuijiaoPanduan(P_dan);
%% 3.弱联通A'=A(+)A(转置)再求P-除对角线都为1;
% step1:A'=A(+)A(转置)
A_ruo=max(A,A');
% step2:求P=A'(+)A'^(2)(+)...(+)A'^(n)%(其中括号加为:max(A,B);括号乘为:KuoHaoCheng(A, B);KedaJZ_caclulation-可达性矩阵)
P_ruo=KedaJZ_caclulation(A_ruo);
% step3:判断除对角线是否都为零:DuijiaoPanduan(P)
disp('3.弱连通判定:');
Duijiao_ruo=DuijiaoPanduan(P_ruo);
%% 最后判定
disp('综上所述:');
if Duijiao_Qiang
QiangLiangtong=1;%记录是否为强联通
disp('这是一个强连通图');
end
if Duijiao_dan
DanxiangLiantong=1;%记录是否为单向联通
disp('这是一个单向连通图');
end
if Duijiao_ruo
RuoLiantong=1;%记录是否为弱联通图
disp('这是一个弱连通图');
end
if ~Duijiao_Qiang&&~Duijiao_dan&&~Duijiao_ruo
disp('这不是一个连通图');
else
YouxiangLiangtong=1;
end
else %为无向图
disp('对于这个无向图');
%% 判定连通图类型:1.联通P=A(+)A^(2)(+)...(+)A^(n)-除对角线都为1;
%% step1:求P=A(+)A^(2)(+)...(+)A^(n)%(其中括号加为:max(A,B);括号乘为:KuoHaoCheng(A, B))
P_Wu=KedaJZ_caclulation(A);
% step2:判断除对角线是否都为零:DuijiaoPanduan(P)
Duijiao_Wu=DuijiaoPanduan(P_Wu);
%% 最后判定
if Duijiao_Wu
WuxiangLiangtong=1;%记录是否为强联通
disp('这是一个连通图');
else
disp('这不是一个连通图');
end
end
function result=DuijiaoPanduan(A)
% % 实例
% A = [1 0 0; 0 2 0; 0 0 3];
% 提取对角线以外的元素
off_diagonal = A(~eye(size(A)));
% 检查非对角线元素是否全为0
if all(off_diagonal == 1)
result=1;
disp('可达性矩阵除了对角线以外的元素都是1');
else
result=0;
disp('可达性矩阵除了对角线以外至少有一个元素不是1');
end
end
function [Wuxiang_EularPath,Youxiang_EularPath,WuxiangPass_path,YouxiangPass_path,OnePrint]=EularPath_determination(A_type,Wuxiang_size,Youxiang_insize,Youxiang_outsize,YouxiangLiangtong,WuxiangLiangtong)
%% 输入:A_type-有向图/无向图;Wuxiang_siz-无向图各个节点的总次数;Youxiang_insize-%有向图各个节点的引入次数;Youxiang_outsize-有向图各个节点的引出次数;YouxiangLiangtong-有向图为连通图;Liangtong_Wu-无向图为连通图
%% 输出:Wuxiang_EularPath-无向欧拉回路判定;Youxiang_EularPath-有向欧拉回路判定; WuxiangPass_path-无向欧拉通路判定;;YouxiangPass_path-有向欧拉通路判定;
%% 输出:OnePrint-一笔画成判定
%% 初始化
Wuxiang_EularPath=0;%初始化无向欧拉回路为0
Youxiang_EularPath=0;%初始化有向欧拉回路为0
WuxiangPass_path=0;%初始化无向欧拉通路为0
YouxiangPass_path=0;%初始化有向欧拉通路为0
OnePrint=0;%初始化不能一笔画成判定
if YouxiangLiangtong||WuxiangLiangtong
%% 无向图判断是否为欧拉图:每个节点次数必须为偶数次
if A_type==0
Wuxiang_size_temp=mod(Wuxiang_size(2,:),2);%若为0即表示可以被整除是2的倍数
%% 判断欧拉回路
if all(Wuxiang_size_temp==0)
Wuxiang_EularPath=1;
disp('该无向图具备欧拉回路是欧拉图');
else
disp('该无向图不具备欧拉回路不是欧拉图');
end
%% 判断欧拉通路[V_i;V_j为奇数;其他为偶数]
%% Step1:找出不相等的是否只有两个
WuxiangPass_path_size=sum(Wuxiang_size_temp);%找出里面为奇数(不为0为1)的个数
if WuxiangPass_path_size==2
WuxiangPass_path_row=find(Wuxiang_size_temp);
%% [V_i;V_j为奇数;]
if all(mod(Wuxiang_size(2,WuxiangPass_path_row),2)~=0)
WuxiangPass_path=1;
disp('该无向图具备欧拉通路');
else
disp('该无向图不具备欧拉通路');
end
else
disp('该有向图不具备欧拉通路');
end
else
Youxiang_size_temp1=Youxiang_insize(2,:)==Youxiang_outsize(2,:);%若为0即表示对应i节点的引入引出次数不等
%% 判断欧拉回路
Youxiang_size_temp=all(Youxiang_size_temp1);%若为0即表示节点i的引入引出次数至少有一个不等
if Youxiang_size_temp
Youxiang_EularPath=1;
disp('该有向图具备欧拉回路是欧拉图');
else
disp('该有向图不具备欧拉回路不是欧拉图');
end
%% 判断欧拉通路[V_i出=V_i入+1;V_j入=V_j出+1;其他相等]
%% Step1:找出不相等的是否只有两个
YouxiangPass_path_size=sum(~Youxiang_size_temp1);
if YouxiangPass_path_size==2
YouxiangPass_path_row=find(~Youxiang_size_temp1);
In=Youxiang_insize(2,:);
Out=Youxiang_outsize(2,:);
%% V_i出=V_i入+1;V_i出=V_i入+1;V_j入=V_j出+1;
if (Out(YouxiangPass_path_row(1))==(In(YouxiangPass_path_row(1))+1)&&In(YouxiangPass_path_row(2))==(Out(YouxiangPass_path_row(2))+1))||(Out(YouxiangPass_path_row(2))==(In(YouxiangPass_path_row(2))+1)&&In(YouxiangPass_path_row(1))==(Out(YouxiangPass_path_row(1))+1))
YouxiangPass_path=1;
disp('该有向图具备欧拉通路');
else
disp('该有向图不具备欧拉通路');
end
else
disp('该有向图不具备欧拉通路');
end
end
if Wuxiang_EularPath||Youxiang_EularPath||WuxiangPass_path||YouxiangPass_path
OnePrint=1;
disp('能一笔画成');
else
disp('不能一笔画成');
end
else
disp('由于不是连通图,不能一笔画成');
end
function hasCycle = hasCycleUsingDFS(A,A_type,A_ruo)
if A_type==1
A=A_ruo;
end
n = size(A, 1); % 矩阵的大小
visited = false(n); % 标记节点是否被访问
parent = zeros(n, 1); % 用于存储每个节点的父节点信息
for i = 1:n
if ~visited(i)
if dfsVisit(A, i, visited, parent)
hasCycle = true;
return;
end
end
end
hasCycle = false;
end
function foundCycle = dfsVisit(matrix, vertex, visited, parent)
visited(vertex) = true; % 标记当前节点为已访问
for i = 1:size(matrix, 1)
% 如果存在邻接点且该点已被访问,并且不是来自父节点,则存在环
if matrix(vertex, i) && visited(i) && parent(vertex) ~= i
foundCycle = true;
return;
end
% 如果邻接点未被访问,则递归访问该点
if matrix(vertex, i) && ~visited(i)
parent(i) = vertex; % 设置当前节点为邻接点的父节点
if dfsVisit(matrix, i, visited, parent)
foundCycle = true;
return;
end
end
end
foundCycle = false;
end
function P_KedaJZ=KedaJZ_caclulation(A)
%% 输入:A-邻接矩阵
%% 输出:P_KedaJZ可达性矩阵
%% 初始化
n=size(A,1);%记录邻接矩阵的行
m=size(A,2);%记录邻接矩阵的列
P_KedaJZ=A;%可达性矩阵初始化
A_temp= A;
%% 计算邻接矩阵
while n~=0
A_temp=KuoHaoCheng(A_temp, A);
n=n-1;
P_KedaJZ=max(P_KedaJZ,A_temp);
if all(A_temp(:)==0)%判断乘法是否提前到极限了
break;
end
end
end
function result =KuoHaoCheng(A, B)
%%
%% 样例
% A=[0,1,0,0,0;0,0,0,1,0;1,0,0,0,0;0,0,0,0,1;0,1,0,0,0];
% B=[0,1,0,0,0;0,0,0,1,0;1,0,0,0,0;0,0,0,0,1;0,1,0,0,0];
%% 定义一个(×)运算
[rows1, cols1] = size(A);%获取矩阵A 的行列
[rows2, cols2] = size(B); %获取矩阵B 的行列
if cols1 ~= rows2
error('矩阵1的列数必须与矩阵2的行数相等');
end
result = zeros(rows1, cols2); % 初始化结果矩阵
for i = 1:rows1
for j = 1:cols2
% 提取矩阵1的第i行和矩阵2的第j列
row = A(i, :)';
col = B(:, j);
% 对每一对元素取min,然后再从结果中取max
result(i, j) = max(min(row, col));
end
end
end
function [Wuxiang_size,Youxiang_insize,Youxiang_outsize,result_Number_of_nodes]=Number_of_nodes(A_type,A)
%% 输入:A_type-邻接矩阵为无向图/有向图;A-邻接矩阵;
%% 输出:Wuxiang_siz-无向图各个节点的总次数;Youxiang_insize-%有向图各个节点的引入次数;Youxiang_outsize-有向图各个节点的引出次数
%% 输出:result_Number_of_nodes-结构体存储所有结果
%% 初始化
Wuxiang_size=[];%无向图各个节点的总次数
Youxiang_insize=[];%有向图各个节点的引入次数
Youxiang_outsize=[];%有向图各个节点的引出次数
%% 次数计算
n=size(A,1);%记录邻接矩阵的行
m=size(A,2);%记录邻接矩阵的列
%% 初始化
result_Number_of_nodes=cell(m,1);
for i=1:m
if A_type==0
%若为无向图,只存在每个节点的总次数=有向图引出次数(该行)+有向图引入次数(该列)
Wuxiang_size_i=sum(A(i,:))+sum(A(:,i));
Wuxiang_size_i=Wuxiang_size_i./2;
disp(['第',num2str(i),'节点的总次数为:',num2str(Wuxiang_size_i)]);
%% 数据记录
Wuxiang_size=[Wuxiang_size,[i;Wuxiang_size_i]];
All=['第',num2str(i),'节点的总次数为:',num2str(Wuxiang_size_i)];
result_Number_of_nodes{i,1}=All;
else
%若为有向图,存在每个节点引出次数(该行)与每个节点引入次数(该列)
Youxiang_insize_i=sum(A(:,i));%引入次数(该列)
disp(['第',num2str(i),'节点引入次数为:',num2str(Youxiang_insize_i)]);
Youxiang_outsize_i=sum(A(i,:));%引出次数(该行)
disp(['第',num2str(i),'节点引出次数为:',num2str(Youxiang_outsize_i)]);
%% 数据记录
Youxiang_insize=[Youxiang_insize,[i;Youxiang_insize_i]];
Youxiang_outsize=[Youxiang_outsize,[i;Youxiang_outsize_i]];
In=['第',num2str(i),'节点引入次数为:',num2str(Youxiang_insize_i)];
Out=['第',num2str(i),'节点引出次数为:',num2str(Youxiang_outsize_i)];
result_Number_of_nodes{i,1}=[In;Out];
end
end
end
function Pop_up_output(A_type,result_Number_of_nodes,QiangLiangtong,DanxiangLiantong,RuoLiantong,YouxiangLiangtong,WuxiangLiangtong,result_of_Long,Wuxiang_Tree,Youxiang_Tree,Wuxiang_EularPath,Youxiang_EularPath,WuxiangPass_path,YouxiangPass_path,OnePrint)
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%第2部分:邻接矩阵的计算+可达性矩阵的求解%%%%%%%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 记录1
result_Number_of_nodes;
%% 记录2
%result_of_Classificztion-存储所有结果
if A_type==1%若为有向图
result_of_Classificztion{1,1}='对于这个有向图';
if QiangLiangtong%记录是否为强联通
result_of_Classificztion{2,1}='这是一个强连通图';
else
result_of_Classificztion{2,1}='这不是一个强连通图';
end
if DanxiangLiantong%记录是否为单向联通
result_of_Classificztion{3,1}='这是一个单向连通图';
else
result_of_Classificztion{3,1}='这不是一个单向连通图';
end
if RuoLiantong%记录是否为弱联通
result_of_Classificztion{3,1}='这是一个弱连通图';
else
result_of_Classificztion{3,1}='这不是一个弱连通图';
end
result_of_Classificztion{4,1}='综上所述:';
if YouxiangLiangtong%记录是否为联通
result_of_Classificztion{5,1}='这是一个连通图';
else
result_of_Classificztion{5,1}='这不是一个连通图';
end
else
result_of_Classificztion{1,1}='对于这个无向图';
if WuxiangLiangtong%记录是否为联通
result_of_Classificztion{2,1}='这是一个连通图';
else
result_of_Classificztion{2,1}='这不是一个连通图';
end
end
%% 记录3
result_of_Long;
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%第3部分:树与欧拉图%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 记录1
%result_of_Tree-存储所有结果
if A_type==1%若为有向图
if Youxiang_Tree
result_of_Tree{1,1}='该有向图为有向树';
else
result_of_Tree{1,1}='该有向图不是树';
end
else
if Wuxiang_Tree
result_of_Tree{1,1}='该无向图为无向树';
else
result_of_Tree{1,1}='该有向图不是树';
end
end
%% 记录2
%result_of_Eular-存储所有结果
if YouxiangLiangtong||WuxiangLiangtong
if A_type==0
%% 判断欧拉回路
if Wuxiang_EularPath
result_of_Eular{1,1}='该无向图具备欧拉回路是欧拉图';
else
result_of_Eular{1,1}='该无向图不具备欧拉回路不是欧拉图';
end
%% 判断欧拉通路
if WuxiangPass_path
result_of_Eular{2,1}='该无向图具备欧拉通路';
else
result_of_Eular{2,1}='该无向图不具备欧拉通路';
end
else
%% 判断欧拉回路
if Youxiang_EularPath
result_of_Eular{1,1}='该有向图具备欧拉回路是欧拉图';
else
result_of_Eular{1,1}='该有向图不具备欧拉回路不是欧拉图';
end
%% 判断欧拉通路
if YouxiangPass_path
result_of_Eular{2,1}='该有向图具备欧拉通路';
else
result_of_Eular{2,1}='该有向图不具备欧拉通路';
end
end
if OnePrint
result_of_Eular{3,1}=['综上所述:','能一笔画成'];
else
result_of_Eular{3,1}=['综上所述:','不能一笔画成'];
end
else
result_of_Eular{1,1}='由于不是连通图,不能一笔画成';
end
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%第4部分:弹窗输出%%%%%%%%%%%%%%%%%
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%result_Number_of_nodes;%每个节点的次数
%result_of_Classificztion
%result_of_Long;
%result_of_Tree
%result_of_Eular
%% 创建一个弹窗
Result=[result_Number_of_nodes;result_of_Classificztion;result_of_Long;result_of_Tree;result_of_Eular];
% 计算文本区域所需的高度
numLines = length(Result); % 文本行数
lineHeight = 40; % 每行文本的高度
textHeight = numLines * lineHeight;
figureHeight = textHeight+40; % 调整弹窗高度
% 调整弹窗的大小
f = figure('Position', [700 90 400 figureHeight], 'Name','图类型', 'NumberTitle','off', 'MenuBar','none');
a = 40; % 用于定位的变量
% 添加白色背景
set(gcf, 'Color', [1 1 1]); % 设置白色背景
% 添加文本到弹窗
for i = 1:numLines
uicontrol(f, 'Style','text', 'String', Result{i}, ...
'Position',[a-40 figureHeight-(i)*lineHeight 380 lineHeight], ...
'Fontsize', 12, 'FontWeight', 'bold', 'BackgroundColor',[1 1 1]);
end
% 创建“确定”和“取消”按钮
okButton = uicontrol(f, 'Style','pushbutton', 'String','确定', ...
'Position',[a-30 figureHeight-20-numLines*lineHeight 180 40], ...
'Fontsize', 24, 'FontWeight', 'bold', 'BackgroundColor',[0 1 0], ...
'Callback','close(gcf)');
cancelButton = uicontrol(f, 'Style','pushbutton', 'String','取消', ...
'Position',[a+170 figureHeight-20-numLines*lineHeight 180 40], ...
'Fontsize', 24, 'FontWeight', 'bold', 'BackgroundColor',[1 0 0], ...
'Callback','close(gcf)');
% 显示弹窗
guidata(f, f);
function [Wuxiang_Tree,Youxiang_Tree]=Tree_determination(A,A_type,RuoLiantong,WuxiangLiangtong,A_ruo)
%% 输入:A-邻接矩阵;A_type-有向图/无向图;WuxiangLiangtong-无向图为连通图;RuoLiantong-弱连通;A_ruo--有向图的弱连通邻接矩阵;
%% 输出:Wuxiang_Tree-无向树判定;Youxiang_Tree-有向树
%% 初始化
Wuxiang_Tree=0;%初始化无向树为0
Youxiang_Tree=0;%初始化有向树为0
%% 树的判定:
%% 无向图判断是否为无向树:不包含回路的连通图【1.是连通图;2.不包含回路:对角线为0】
if A_type==0&&WuxiangLiangtong==1
%% 2.不包含回路:对角线为0;
WuxianghasCycle = hasCycleUsingDFS(A,A_type,A_ruo);
if WuxianghasCycle==0
Wuxiang_Tree=1;
disp('该无向图为无向树');
else
disp('该有向图不是树');
end
end
%% 有向图判断是否为有向树:不考虑方向为无向图时为不包含回路的连通图【1.变为无向图;2.是连通图;3.不包含回路:对角线为0】
%% 1.是否为弱连通:A'=A(+)A(转置)再求P-除对角线都为1;【变为无向图(A'=A(+)A(转置))+是连通图(P-除对角线都为1)】
if A_type&&RuoLiantong
%% 2.不包含回路:对角线为0;
YouxianghasCycle = hasCycleUsingDFS(A,A_type,A_ruo);
if YouxianghasCycle==0
Youxiang_Tree=1;
disp('该有向图为有向树');
else
disp('该有向图不是树');
end
end
function Long_res=Vi_to_Vj_Long_caclulation(A,V_i,V_j,Long)
%% 输入:A-邻接矩阵;V_i-输入节点i;V_j-输入节点j;Long-要求长度
%% 输出:Long_res-V_i和V_j的长度为Long的回路(通路)条数
A_sum=A^Long;
Long_res=A_sum(V_i,V_j);
end