随机创建指定顶点数的欧拉图并求欧拉回路基于matlab

转载请注明出处

以下程序实现内容:

  1. 随机创建指定顶点的连通图
  2. 随机创建指定顶点的欧拉图
  3. 判断某边是否为割边
  4. 求某图的联通分量
  5. 求欧拉图中的一条欧拉回路
  6. DFS遍历整个图
clc,clear
d = oulaliantongtu(100,1)
[path] = main(d)
%% n为点的个数,s为1则画出图。生成一个对称连通图,两点之间只有一条边
function [pic]=oulaliantongtu(n,s)
[ST,~]=graphminspantree(sparse(ones(n-1)),'Method','Kruskal');% 为确保连通性,做一个n-1个结点的最小生成树
st=full(ST);% 稀疏矩阵ST转换为满存储结构st
st = max(st,st');% 转化为对称矩阵
c = round(rand(n-1)); %生成一个(n-1)x(n-1)的随机0-1矩阵
c(logical(eye(n-1))) = 0;%将上述随机矩阵的对角线上元素变为0
c = min(c,c');% 转化为对称矩阵,为了使得点与点之间元素可以少点,选用min,也可以用max
pic = max(st,c);% st与c结合生成随机(n-1)x(n-1)连通图
pic(:,n)=0;pic(n,:)=0; % 增加第n个结点
S = find(mod(sum(pic,2),2)); %查看度为奇数的点
for m = 1:size(S,1) % 为了保证每个点的度均为偶数(为使得该连通图一定存在欧拉回路)
    pic(S(m),n)=1; % 使得度为奇数的结点与第n个结点都联通
    pic(n,S(m))=1; % 使得第n个结点与度为奇数的结点都联通
end
if isempty(S) % 考虑特殊情况,即n-1个结点已经构成欧拉图
    if pic(1,2) == 1 % 如果第一个结点和第二个结点已经联通
        pic(1,2) = 0;pic(2,1) = 0; % 使得第一个结点和第二个结点不连通
        pic(1,n) = 1;pic(n,1) = 1; % 使得第一个结点和第n个结点连通
        pic(2,n) = 1;pic(n,2) = 1; % 使得第二个结点和第n个结点连通
    else
        pic(1,2) = 1;pic(2,1) = 1; % 使得第一个结点和第二个结点连通
        pic(1,n) = 1;pic(n,1) = 1; % 使得第一个结点和第n个结点连通
        pic(2,n) = 1;pic(n,2) = 1; % 使得第二个结点和第n个结点连通
    end
end % 使得生成n个结点的欧拉图
if s==1 % 如果s=1
view(biograph(tril(pic),[],'ShowArrows','off'));% 则画出生成的欧拉图
end
end
%% 这里先写一个函数,从第n个点走到下一个点,迫不得已才能走割边
function [d,n] = getnext(d,n)
ns = find(d(n,:));% ns为点n连接的点的集合
if length(ns) == 1% 如果只有一个点和点n联通
    d(ns,n) = 0;d(n,ns) = 0;% 那么只能从点n到这个点
    n = ns; % 走到下一个点
else
    for i = ns % 遍历可走点的集合
        if sum(d(i,:)) ~= 1 % 如果点i可通点不只有点n则可走点i
        if wheathercuting(d,n,i) == 1%如果n-i不是割边
            d(i,n) = 0;d(n,i) = 0; %那么可以考虑从点n到这个点
            n = i; % 走到下一个点
            break % 既然到了下一个点便可退出上一个点的可走点集合循环
        end
        end
    end
end
end
%% d为一欧拉图的邻接矩阵,此函数求得其一个欧拉回路
function [path] = main(d)
n = 1;
path(1,(sum(sum(d))/2)) = 0;% 因为图的边数确定,即可预先为路径数组分配内存
path(1,1) = n;% 设置从点1开始出发
for x = 1:(sum(sum(d))/2) % 有多少条边循环多少次
    [d,n] = getnext(d,n); % 走啊走啊走
    path(1,x+1) = n; % 存已走点到路径列表
    %view(biograph(tril(d),[],'ShowArrows','off'));
end
view(biograph(tril(d),[],'ShowArrows','off')) % 查看走完后之后的图(走过的边就删除)
end
%% 此函数判断该边是否为割边,是割边返回0,不是割边返回1
function [symbol] = wheathercuting(d,n,i)
% 其中d为一对称联通图,n为边的一个顶点,i为边的另一个顶点
dnews = d;dnews(i,n) = 0;dnews(n,i) = 0;% 删除边n-i后的图的邻接矩阵为dnews
tot_cc = 0;% 初始化联通分量的值
for p=1:length(dnews) %利用
    for to=1:length(dnews) %函数
        if dnews(p,to) == 1 %dfs
            tot_cc = tot_cc + 1; %求得
            dnews = dfs(p,dnews); %dnews的连通分量
        end
    end
end
if tot_cc == 1 % 如果tot_cc = 1
    symbol = 1; % 则此边不是割边,返回1
else
    symbol = 0; % 反之返回0
end
end
%% 此函数用DFS为判断一个邻接矩阵的联通分量做准备
function [d] = dfs(p,d)
for to=1:length(d)
    if d(p,to) == 1
        d(p,to) = 0;d(to,p) = 0;
        [d] = dfs(to,d);
    end
end
end
  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值