最小生成树matlab程序

合集下载

最小生成树matlab程序

最小生成树matlab程序

%n表示节点数,A表示弧权矩阵function [I]=MinTree(n,A)k=1; %记录A中不同正数的个数for(i=1:n-1)for(j=i+1:n) %此循环是查找A中所有不同的正数if(A(i,j)>0)x(k)=A(i,j); %数组x记录A中不同的正数kk=1; %临时变量for(s=1:k-1)if(x(k)==x(s))kk=0;break;end;end %排除相同的正数k=k+kk;end;end;endk=k-1 %显示A中所有不同正数的个数for(i=1:k-1)for(j=i+1:k) %将x中不同的正数从小到大排序if(x(j)<x(i))xx=x(j);x(j)=x(i);x(i)=xx;end;end;endT(n,n)=0; %将矩阵T中所有的元素赋值为0q=0; %记录加入到树T中的边数for(s=1:k)if(q==n)break;end %获得最小生成树T, 算法终止for(i=1:n-1)for(j=i+1:n)if (A(i,j)==x(s))T(i,j)=x(s);T(j,i)=x(s); %加入边到树T中TT=T; %临时记录Twhile(1)pd=1; %砍掉TT中所有的树枝for(y=1:n)kk=0;for(z=1:n)if(TT(y,z)>0)kk=kk+1;zz=z;end;end %寻找TT中的树枝if(kk==1)TT(y,zz)=0;TT(zz,y)=0;pd=0;end;end %砍掉TT中的树枝if(pd)break;end;end %已砍掉了TT中所有的树枝pd=0; %判断TT中是否有圈for(y=1:n-1)for(z=y+1:n)if(TT(y,z)>0)pd=1;break;end;end;endif(pd)T(i,j)=0;T(j,i)=0; %假如TT中有圈else q=q+1;end;end;end;end;endT %显示近似最小生成树T, 程序结束。

matlab图论程序算法大全

matlab图论程序算法大全

图论算法matlab实现求最小费用最大流算法的 MATLAB 程序代码如下:n=5;C=[0 15 16 0 00 0 0 13 140 11 0 17 00 0 0 0 80 0 0 0 0]; %弧容量b=[0 4 1 0 00 0 0 6 10 2 0 3 00 0 0 0 20 0 0 0 0]; %弧上单位流量的费用wf=0;wf0=Inf; %wf 表示最大流量, wf0 表示预定的流量值for(i=1:n)for(j=1:n)f(i,j)=0;end;end %取初始可行流f 为零流while(1)for(i=1:n)for(j=1:n)if(j~=i)a(i,j)=Inf;end;end;end%构造有向赋权图for(i=1:n)for(j=1:n)if(C(i,j)>0&f(i,j)==0)a(i,j)=b(i,j); elseif(C(i,j)>0&f(i,j)==C(i,j))a(j,i)=-b(i,j);elseif(C(i,j)>0)a(i,j)=b(i,j);a(j,i)=-b(i,j);end;end;end for(i=2:n)p(i)=Inf;s(i)=i;end %用Ford 算法求最短路, 赋初值for(k=1:n)pd=1; %求有向赋权图中vs 到vt 的最短路for(i=2:n)for(j=1:n)if(p(i)>p(j)+a(j,i))p(i)=p(j)+a(j,i);s( i)=j;pd=0;end;end;endif(pd)break;end;end %求最短路的Ford 算法结束if(p(n)==Inf)break;end %不存在vs 到vt 的最短路, 算法终止. 注意在求最小费用最大流时构造有向赋权图中不会含负权回路, 所以不会出现k=ndvt=Inf;t=n; %进入调整过程, dvt 表示调整量while(1) %计算调整量if(a(s(t),t)>0)dvtt=C(s(t),t)-f(s(t),t); %前向弧调整量elseif(a(s(t),t)<0)dvtt=f(t,s(t));end %后向弧调整量if(dvt>dvtt)dvt=dvtt;endif(s(t)==1)break;end %当t 的标号为vs 时, 终止计算调整量t=s(t);end %继续调整前一段弧上的流fpd=0;if(wf+dvt>=wf0)dvt=wf0-wf;pd=1;end%如果最大流量大于或等于预定的流量值t=n;while(1) %调整过程if(a(s(t),t)>0)f(s(t),t)=f(s(t),t)+dvt; %前向弧调整elseif(a(s(t),t)<0)f(t,s(t))=f(t,s(t))-dvt;end %后向弧调整if(s(t)==1)break;end %当t 的标号为vs 时, 终止调整过程t=s(t);endif(pd)break;end%如果最大流量达到预定的流量值wf=0; for(j=1:n)wf=wf+f(1,j);end;end %计算最大流量zwf=0;for(i=1:n)for(j=1:n)zwf=zwf+b(i,j)*f(i,j);end;end%计算最小费用f %显示最小费用最大流图 6-22wf %显示最小费用最大流量zwf %显示最小费用, 程序结束__Kruskal 避圈法:Kruskal 避圈法的MATLAB 程序代码如下:n=8;A=[0 2 8 1 0 0 0 02 0 6 0 1 0 0 08 6 0 7 5 1 2 01 0 7 0 0 0 9 00 1 5 0 0 3 0 80 0 1 0 3 0 4 60 0 2 9 0 4 0 30 0 0 0 8 6 3 0];k=1; %记录A中不同正数的个数for(i=1:n-1)for(j=i+1:n) %此循环是查找A中所有不同的正数if(A(i,j)>0)x(k)=A(i,j); %数组x 记录A中不同的正数kk=1; %临时变量for(s=1:k-1)if(x(k)==x(s))kk=0;break;end;end %排除相同的正数k=k+kk;end;end;endk=k-1 %显示A中所有不同正数的个数for(i=1:k-1)for(j=i+1:k) %将x 中不同的正数从小到大排序if(x(j)<x(i))xx=x(j);x(j)=x(i);x(i)=xx;end;end;endT(n,n)=0; %将矩阵T 中所有的元素赋值为0q=0; %记录加入到树T 中的边数for(s=1:k)if(q==n)break;end %获得最小生成树T, 算法终止for(i=1:n-1)for(j=i+1:n)if(A(i,j)==x(s))T(i,j)=x(s);T(j,i)=x(s); %加入边到树T 中TT=T; %临时记录Twhile(1)pd=1; %砍掉TT 中所有的树枝for(y=1:n)kk=0;for(z=1:n)if(TT(y,z)>0)kk=kk+1;zz=z;end;end %寻找TT 中的树枝if(kk==1)TT(y,zz)=0;TT(zz,y)=0;pd=0;end;end %砍掉TT 中的树枝if(pd)break;end;end %已砍掉了TT 中所有的树枝pd=0; %判断TT 中是否有圈for(y=1:n-1)for(z=y+1:n)if(TT(y,z)>0)pd=1;break;end;end;end if(pd)T(i,j)=0;T(j,i)=0; %假如TT 中有圈else q=q+1;end;end;end;end;endT %显示近似最小生成树T, 程序结束用Warshall-Floyd 算法求任意两点间的最短路.n=8;A=[0 2 8 1 Inf Inf Inf Inf2 0 6 Inf 1 Inf Inf Inf8 6 0 7 5 1 2 Inf1 Inf 7 0 Inf Inf 9 Inf Inf 1 5 Inf 0 3 Inf 8 Inf Inf 1 Inf 3 0 4 6Inf Inf 2 9 Inf 4 0 3Inf Inf Inf Inf 8 6 3 0]; % MATLAB 中, Inf 表示∞D=A; %赋初值for(i=1:n)for(j=1:n)R(i,j)=j;end;end %赋路径初值for(k=1:n)for(i=1:n)for(j=1:n)if(D(i,k)+D(k,j)<D(i,j))D(i,j )=D(i,k)+D(k,j); %更新dijR(i,j)=k;end;end;end %更新rijk %显示迭代步数D %显示每步迭代后的路长R %显示每步迭代后的路径pd=0;for i=1:n %含有负权时if(D(i,i)<0)pd=1;break;end;end %存在一条含有顶点vi 的负回路if(pd)break;end %存在一条负回路, 终止程序end %程序结束利用 Ford--Fulkerson 标号法求最大流算法的MATLAB 程序代码如下:n=8;C=[0 5 4 3 0 0 0 00 0 0 0 5 3 0 00 0 0 0 0 3 2 00 0 0 0 0 0 2 00 0 0 0 0 0 0 40 0 0 0 0 0 0 30 0 0 0 0 0 0 50 0 0 0 0 0 0 0]; %弧容量for(i=1:n)for(j=1:n)f(i,j)=0;end;end %取初始可行流f 为零流for(i=1:n)No(i)=0;d(i)=0;end %No,d 记录标号图 6-19while(1)No(1)=n+1;d(1)=Inf; %给发点vs 标号while(1)pd=1; %标号过程for(i=1:n)if(No(i)) %选择一个已标号的点vifor(j=1:n)if(No(j)==0&f(i,j)<C(i,j)) %对于未给标号的点vj, 当vivj 为非饱和弧时No(j)=i;d(j)=C(i,j)-f(i,j);pd=0;if(d(j)>d(i))d(j)=d(i);endelseif(No(j)==0&f(j,i)>0) %对于未给标号的点vj, 当vjvi 为非零流弧时No(j)=-i;d(j)=f(j,i);pd=0;if(d(j)>d(i))d(j)=d(i);end;end;end;end;endif(No(n)|pd)break;end;end%若收点vt 得到标号或者无法标号, 终止标号过程if(pd)break;end %vt 未得到标号, f 已是最大流, 算法终止dvt=d(n);t=n; %进入调整过程, dvt 表示调整量while(1)if(No(t)>0)f(No(t),t)=f(No(t),t)+dvt; %前向弧调整elseif(No(t)<0)f(No(t),t)=f(No(t),t)-dvt;end %后向弧调整if(No(t)==1)for(i=1:n)No(i)=0;d(i)=0; end;break;end %当t 的标号为vs 时, 终止调整过程t=No(t);end;end; %继续调整前一段弧上的流fwf=0;for(j=1:n)wf=wf+f(1,j);end %计算最大流量f %显示最大流wf %显示最大流量No %显示标号, 由此可得最小割, 程序结束图论程序大全程序一:关联矩阵和邻接矩阵互换算法function W=incandadf(F,f)if f==0m=sum(sum(F))/2;n=size(F,1);W=zeros(n,m);k=1;for i=1:nfor j=i:nif F(i,j)~=0W(i,k)=1;W(j,k)=1;k=k+1;endendendelseif f==1m=size(F,2);n=size(F,1);W=zeros(n,n);for i=1:ma=find(F(:,i)~=0);W(a(1),a(2))=1;W(a(2),a(1))=1;endelsefprint('Please imput the right value of f');endW;程序二:可达矩阵算法function P=dgraf(A) n=size(A,1);P=A;for i=2:nP=P+A^i;endP(P~=0)=1;P;程序三:有向图关联矩阵和邻接矩阵互换算法function W=mattransf(F,f)if f==0m=sum(sum(F));n=size(F,1);W=zeros(n,m);k=1;for i=1:nfor j=i:nif F(i,j)~=0W(i,k)=1;W(j,k)=-1;k=k+1;endendendelseif f==1m=size(F,2);n=size(F,1);W=zeros(n,n);for i=1:ma=find(F(:,i)~=0);if F(a(1),i)==1W(a(1),a(2))=1;elseW(a(2),a(1))=1;endendelsefprint('Please imput the right value of f');endW;第二讲:最短路问题程序一:Dijkstra算法(计算两点间的最短路)function [l,z]=Dijkstra(W)n = size (W,1); for i = 1 :nl(i)=W(1,i);z(i)=0;endi=1;while i<=nfor j =1 :nif l(i)>l(j)+W(j,i)l(i)=l(j)+W(j,i);z(i)=j-1;if j<ii=j-1;endendendi=i+1;end程序二:floyd算法(计算任意两点间的最短距离)function [d,r]=floyd(a)n=size(a,1);d=a;for i=1:nfor j=1:nr(i,j)=j;endendr;for k=1:nfor i=1:nfor j=1:nif d(i,k)+d(k,j)<d(i,j)d(i,j)=d(i,k)+d(k,j);r(i,j)=r(i,k);endendendend程序三:n2short.m 计算指定两点间的最短距离function [P u]=n2short(W,k1,k2)n=length(W);U=W;m=1;while m<=nfor i=1:nfor j=1:nif U(i,j)>U(i,m)+U(m,j)U(i,j)=U(i,m)+U(m,j);endendendm=m+1;endu=U(k1,k2);P1=zeros(1,n);k=1;P1(k)=k2;V=ones(1,n)*inf;kk=k2;while kk~=k1for i=1:nV(1,i)=U(k1,kk)-W(i,kk);if V(1,i)==U(k1,i)P1(k+1)=i;kk=i;k=k+1;endendendk=1;wrow=find(P1~=0);for j=length(wrow):-1:1P(k)=P1(wrow(j));k=k+1;endP;程序四、n1short.m(计算某点到其它所有点的最短距离)function[Pm D]=n1short(W,k)n=size(W,1);D=zeros(1,n);for i=1:n[P d]=n2short(W,k,i);Pm{i}=P;D(i)=d;end程序五:pass2short.m(计算经过某两点的最短距离)function [P d]=pass2short(W,k1,k2,t1,t2)[p1 d1]=n2short(W,k1,t1);[p2 d2]=n2short(W,t1,t2);[p3 d3]=n2short(W,t2,k2);dt1=d1+d2+d3;[p4 d4]=n2short(W,k1,t2);[p5 d5]=n2short(W,t2,t1);[p6 d6]=n2short(W,t1,k2);dt2=d4+d5+d6;if dt1<dt2d=dt1;P=[p1 p2(2:length(p2)) p3(2:length(p3))];elsed=dt1;p=[p4 p5(2:length(p5)) p6(2:length(p6))];endP;d;第三讲:最小生成树程序一:最小生成树的Kruskal算法function [T c]=krusf(d,flag)if nargin==1n=size(d,2);m=sum(sum(d~=0))/2;b=zeros(3,m);k=1;for i=1:nfor j=(i+1):nif d(i,j)~=0b(1,k)=i;b(2,k)=j;b(3,k)=d(i,j);k=k+1;endendendelseb=d;endn=max(max(b(1:2,:)));m=size(b,2);[B,i]=sortrows(b',3);B=B';c=0;T=[];k=1;t=1:n;for i=1:mif t(B(1,i))~=t(B(2,i))T(1:2,k)=B(1:2,i);c=c+B(3,i);k=k+1;tmin=min(t(B(1,i)),t(B(2,i)));tmax=max(t(B(1,i)),t(B(2,i)));for j=1:nif t(j)==tmaxt(j)=tmin;endendendif k==nbreak;endendT;c;程序二:最小生成树的Prim算法function [T c]=Primf(a)l=length(a);a(a==0)=inf;k=1:l;listV(k)=0;listV(1)=1;e=1;while (e<l)min=inf;for i=1:lif listV(i)==1for j=1:lif listV(j)==0 & min>a(i,j)min=a(i,j);b=a(i,j);s=i;d=j;endendendendlistV(d)=1;distance(e)=b;source(e)=s;destination(e)=d;e=e+1;endT=[source;destination]; for g=1:e-1c(g)=a(T(1,g),T(2,g));endc;另外两种程序最小生成树程序1(prim 算法构造最小生成树)a=[inf 50 60 inf inf inf inf;50 inf inf 65 40 inf inf;60 inf inf 52 inf inf 45;...inf 65 52 inf 50 30 42;inf 40 inf 50 inf 70 inf;inf inf inf 30 70 inf inf;...inf inf 45 42 inf inf inf];result=[];p=1;tb=2:length(a);while length(result)~=length(a)-1temp=a(p,tb);temp=temp(:);d=min(temp);[jb,kb]=find(a(p,tb)==d);j=p(jb(1));k=tb(kb(1));result=[result,[j;k;d]];p=[p,k];tb(find(tb==k))=[];endresult最小生成树程序2(Kruskal 算法构造最小生成树)clc;clear;a(1,2)=50; a(1,3)=60; a(2,4)=65; a(2,5)=40;a(3,4)=52;a(3,7)=45; a(4,5)=50; a(4,6)=30;a(4,7)=42; a(5,6)=70;[i,j,b]=find(a);data=[i';j';b'];index=data(1:2,:);loop=max(size(a))-1;result=[];while length(result)<looptemp=min(data(3,:));flag=find(data(3,:)==temp);flag=flag(1);v1=data(1,flag);v2=data(2,flag);if index(1,flag)~=index(2,flag)result=[result,data(:,flag)];endindex(find(index==v2))=v1;data(:,flag)=[];index(:,flag)=[];endresult第四讲:Euler图和Hamilton图程序一:Fleury算法(在一个Euler图中找出Euler环游)注:包括三个文件;fleuf1.m, edf.m, flecvexf.mfunction [T c]=fleuf1(d)%注:必须保证是Euler环游,否则输出T=0,c=0 n=length(d);b=d;b(b==inf)=0;b(b~=0)=1;m=0;a=sum(b);eds=sum(a)/2;ed=zeros(2,eds);vexs=zeros(1,eds+1);matr=b;for i=1:nif mod(a(i),2)==1m=m+1;endendif m~=0fprintf('there is not exit Euler path.\n')T=0;c=0;endif m==0vet=1;flag=0;t1=find(matr(vet,:)==1);for ii=1:length(t1)ed(:,1)=[vet,t1(ii)];vexs(1,1)=vet;vexs(1,2)=t1(ii);matr(vexs(1,2),vexs(1,1))=0;flagg=1;tem=1;while flagg[flagg ed]=edf(matr,eds,vexs,ed,tem); tem=tem+1;if ed(1,eds)~=0 & ed(2,eds)~=0T=ed;T(2,eds)=1;c=0;for g=1:edsc=c+d(T(1,g),T(2,g));endflagg=0;break;endendendendfunction[flag ed]=edf(matr,eds,vexs,ed,tem)flag=1;for i=2:eds[dvex f]=flecvexf(matr,i,vexs,eds,ed,tem);if f==1flag=0;break;endif dvex~=0ed(:,i)=[vexs(1,i) dvex];vexs(1,i+1)=dvex;matr(vexs(1,i+1),vexs(1,i))=0;elsebreak;endendfunction [dvex f]=flecvexf(matr,i,vexs,eds,ed,temp) f=0;edd=find(matr(vexs(1,i),:)==1);dvex=0;dvex1=[];ded=[];if length(edd)==1dvex=edd;elsedd=1;dd1=0;kkk=0;for kk=1:length(edd)m1=find(vexs==edd(kk));if sum(m1)==0dvex1(dd)=edd(kk);dd=dd+1;dd1=1;elsekkk=kkk+1;endendif kkk==length(edd)tem=vexs(1,i)*ones(1,kkk);edd1=[tem;edd];for l1=1:kkklt=0;ddd=1;for l2=1:edsif edd1(1:2,l1)==ed(1:2,l2)lt=lt+1;endendif lt==0ded(ddd)=edd(l1); ddd=ddd+1;endendendif temp<=length(dvex1)dvex=dvex1(temp);elseif temp>length(dvex1) & temp<=length(ded)dvex=ded(temp);elsef=1;endend程序二:Hamilton改良圈算法(找出比较好的Hamilton路)function [C d1]= hamiltonglf(v)%d表示权值矩阵%C表示算法最终找到的Hamilton圈。

fp-tree算法的matlab程序

fp-tree算法的matlab程序

FP树算法的MATLAB程序示例FP树(频繁模式树)算法是一种用于挖掘频繁模式的数据挖掘算法。

下面是一个基于事实的FP树算法的MATLAB 程序示例:function [frequent_patterns] = fp_tree(data, min_support) % 构建频繁模式树root = create_tree(data);% 获取频繁项集frequent_patterns = mine_patterns(root, min_support);endfunction [root] = create_tree(data)root = struct('item', 'null', 'count', 0, 'children', {});% 统计每个项的计数item_counts = containers.Map();for i = 1:length(data)itemset = data{i};for j = 1:length(itemset)item = itemset{j};if isKey(item_counts, item)item_counts(item) = item_counts(item)+ 1;elseitem_counts(item) = 1;endendend% 删除不满足最小支持度的项items = keys(item_counts);for i = 1:length(items)item = items{i};if item_counts(item) < min_supportremove(item_counts, item);endend% 如果没有满足最小支持度的项,返回空树if isempty(keys(item_counts))return;end% 对每个事务中的项按照支持度降序排序for i = 1:length(data)itemset = data{i};[~, sorted_indices] = sort(cellfun(@(x) item_counts(x), itemset), 'descend');data{i} = itemset(sorted_indices);end% 构建树for i = 1:length(data)itemset = data{i};insert_tree(root, itemset, item_counts);endendfunction [] = insert_tree(node, itemset, item_counts)if isempty(itemset)return;enditem = itemset{1};child = find_child(node, item);if isempty(child)child = struct('item', item, 'count', item_counts(item), 'children', {});node.children{end+1} = child;elsechild.count = child.count + item_counts(item);endinsert_tree(child, itemset(2:end), item_counts);endfunction [child] = find_child(node, item)children = node.children;for i = 1:length(children)if strcmp(children{i}.item, item)child = children{i};return;endendchild = [];endfunction [frequent_patterns] = mine_patterns(root, min_support)frequent_patterns = struct('pattern', {}, 'support', []);if isempty(root.children)return;endfor i = 1:length(root.children)child = root.children{i};pattern = {child.item};support = child.count;frequent_patterns(end+1) = struct('pattern', pattern, 'support', support);subtree_data = get_subtree_data(child);subtree_patterns = fp_tree(subtree_data, min_support);frequent_patterns = [frequent_patterns, subtree_patterns];endendfunction [subtree_data] = get_subtree_data(node)subtree_data = {};if isempty(node.children)return;endsubtree_data = cell(1, node.count);for i = 1:length(node.children)child = node.children{i};for j = 1:child.countsubtree_data{j} = [subtree_data{j}, child.item];endendend这是一个简化的FP树算法的MATLAB实现。

数学建模-最小生成树-kruskal算法及各种代码之欧阳史创编

数学建模-最小生成树-kruskal算法及各种代码之欧阳史创编

kruskal算法及代码---含伪代码、c代码、matlab、pascal等代码K r u s k a l算法每次选择n- 1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。

注意到所选取的边若产生环路则不可能形成一棵生成树。

K r u s k a l算法分e 步,其中e 是网络中边的数目。

按耗费递增的顺序来考虑这e 条边,每次考虑一条边。

当考虑某条边时,若将其加入到已选边的集合中会出现环路,则将其抛弃,否则,将它选入。

目录Kruskal算法1.算法定义举例描述Kruskal算法的代码实现1.伪代码C代码实现matlab代码实现pascal代码实现Kruskal算法1.算法定义举例描述Kruskal算法的代码实现1.伪代码C代码实现matlab代码实现pascal代码实现算法定义克鲁斯卡尔算法假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。

之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。

依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。

举例描述克鲁斯卡尔算法(Kruskal's algorithm)是两个经典的最小生成树算法的较为简单理解的一个。

这里面充分体现了贪心算法的精髓。

大致的流程可以用一个图来表示。

这里的图的选择借用了Wikipedia上的那个。

非常清晰且直观。

首先第一步,我们有一张图,有若干点和边如下图所示:第一步我们要做的事情就是将所有的边的长度排序,用排序的结果作为我们选择边的依据。

Kruskal算法寻找最小树的matlab程序

Kruskal算法寻找最小树的matlab程序

Kruskal算法寻找最小树的matlab程序function tree=kruskal(d) %矩阵d为无向图的权矩阵,且是对称矩阵N=size(d,1);k=0; %记录图中边的条数I=max(max(d)); %I作为无穷大edge=zeros(N*(N-1)/2,3);%用于存储图中所有的边,边的条数最多为n*(n-1)/2for i=1:N-1 %因为权矩阵是对称阵,所以只用上三角矩阵。

for j=i+1:Nif d(i,j)<Ik=k+1;edge(k,1)=i;edge(k,2)=j;edge(k,3)=d(i,j);endendendedge=edge(1:k,:); %删除多余的行。

o_edge=edge; %用于存储排序后的边及边的端点。

for i=1:k-1 %用选择排序法进行升序排序for j=i+1:kif o_edge(i,3)>o_edge(j,3)temp=o_edge(i,:);o_edge(i,:)=o_edge(j,:);o_edge(j,:)=temp;endendendtree=zeros(N-1,3); %用于存放最小树中的边及边的端点,最小树中的边数为节点数减1 tree(1:2,:)=o_edge(1:2,:); %两条边一定不能构成圈,所以前面最小的两条边一定在最小树中。

line=3;for i=3:kif line==N %如果line=N说明tree矩阵已填满,最小树已经找到,跳出循环break;elseif line<Nif isempty(find(tree(:,1:2)==o_edge(i,1), 1))||isempty(find(tree(:,1:2)==o_edge(i,2), 1))%判断tree中已经确定的的所有边中的节点是否和新增加的边的两个端点都重复,若新边的两个端点不都重复,则为真%直接说明新边符合条件,加入tree中。

离散数学大作业——编程实现最小生成树

离散数学大作业——编程实现最小生成树

离散数学大作业——编程实现最小生成树学院:电子工程学院班级:021051学号:*********名:***一、最小生成树概念:设G=(V,E)是无向连通带权图,即一个网络。

E中每条边(v,w)的权为c[v,w]。

所有生成树G’上各边权的总和最小的生成树称为G的最小生成树。

二、prim算法(贪心思想)设图G =(V,E),其生成树的顶点集合为U。

1.把v0放入U。

2.在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。

3.把2找到的边的v加入U集合。

如果U集合已有n个元素,则结束,否则继续执行2其算法的时间复杂度为O(n^2)三、程序源代码# include<stdio.h># include<malloc.h># define m 6# define n 11 typedef struct {int i,tag;char s;}vertice;typedef struct {int a,b,tag;int weight;}edge;vertice v[m];edge e[n];void inititate();void sort();void chuli();int biaoji( edge *s); void print();void main() {inititate();sort();chuli();print();}void inititate() {int i;printf("输入图的%d个顶点:\n",m);for(i=0;i<m;i++) {v[i].i=i+1;v[i].tag=0;scanf("%c",&v[i].s);getchar();}printf("\n输入%d条边的两端顶点及权:\n",n);for(i=0;i<n;i++) {scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].weight);e[i].tag=0;}}int biaoji( edge *s) {int i,j;i=s->a;j=s->b;if(v[i].tag==0 || v[j].tag==0) {v[i].tag=1;v[i].tag=1;s->tag=1;return 1;}return 0;}void print() {int i,j=0;printf("\n最小生成树的边为:\n");for(i=0;i<n&&j<m-1;i++)if(e[i].tag==1) {printf("<%d-%d> ",e[i].a,e[i].b);j++;}printf("\n\n");}void sort() {edge s;int i,j;for(i=0;i<n-1;i++) {for(j=i+1;j<n;j++) {if(e[i].weight>e[j].weight) {s=e[i];e[i]=e[j];e[j]=s;}}}}void chuli() {int i,j=0;edge *s;for(i=0;i<n&&j<m;i++) {s=&e[i];if(biaoji(s)==1)j++;}}四、实验结果输入图的6个顶点:1 2 3 4 5 6输入11条边的权及两端顶点:1 2 11 4 61 6 91 3 112 3 22 4 33 5 83 6 74 5 104 6 45 6 5最小生成树的边为:<1-2> <2-3> <2-4> <4-6> <5-6> Press any key to continue。

数学建模-最小生成树-kruskal算法及各种代码

数学建模-最小生成树-kruskal算法及各种代码

kruskal算法及代码之阳早格格创做---含真代码、c代码、matlab、pascal等代码K r u s k a l算法屡屡采用n- 1条边,所使用的贪婪规则是:从剩下的边中采用一条不会爆收环路的具备最小泯灭的边加进已采用的边的集中中.注意到所采用的边若爆收环路则不可能产死一棵死成树.K r u s k a l算法分e 步,其中e 是搜集中边的数目.按泯灭递加的程序去思量那e 条边,屡屡思量一条边.当思量某条边时,若将其加进到已选边的集中中会出现环路,则将其扬弃,可则,将它选进.目录Kruskal算法1.算法定义举例形貌Kruskal算法的代码真止1.真代码C代码真止matlab代码真止pascal代码真止Kruskal算法1.算法定义举例形貌Kruskal算法的代码真止1.真代码C代码真止matlab代码真止pascal代码真止算法定义克鲁斯卡我算法假设WN=(V,{E}) 是一个含有n 个顶面的连通网,则依照克鲁斯卡我算法构制最小死成树的历程为:先构制一个只含n 个顶面,而边集为空的子图,若将该子图中各个顶面瞅成是各棵树上的根结面,则它是一个含有n 棵树的一个森林.之后,从网的边集E 中采用一条权值最小的边,若该条边的二个顶面分属分歧的树,则将其加进子图,也便是道,将那二个顶面分别地方的二棵树合成一棵树;反之,若该条边的二个顶面已降正在共一棵树上,则不可与,而该当与下一条权值最小的边再试之.依次类推,曲至森林中惟有一棵树,也即子图中含有n-1条边为止.举例形貌克鲁斯卡我算法(Kruskal's algorithm)是二个典范的最小死成树算法的较为简朴明白的一个.那内里充分体现了贪心算法的粗髓.大概的过程不妨用一个图去表示.那里的图的采用借用了Wikipedia上的那个.非常浑晰且曲瞅.最先第一步,咱们有一弛图,有若搞面战边如下图所示:第一步咱们要搞的事务便是将所有的边的少度排序,用排序的截止动做咱们采用边的依据.那里再次体现了贪心算法的思维.资材排序,对付局部最劣的资材举止采用.排序完毕后,咱们率先采用了边AD.那样咱们的图便形成了第二步,正在剩下的变中觅找.咱们找到了CE.那里边的权沉也是5依次类推咱们找到了6,7,7.完毕之后,图形成了那个格式..下一步便是闭键了.底下采用那条边呢?BC大概者EF 吗?皆不是,纵然目前少度为8的边是最小的已采用的边.然而是目前他们已经连通了(对付于BC不妨通过CE,EB去对接,类似的EF不妨通过EB,BA,AD,DF去接连).所以咱们不需要采用他们.类似的BD也已经连通了(那里上图的连通线用白色表示了).末尾便剩下EG战FG了.天然咱们采用了EG.末尾乐成的图便是下图:.到那里所有的边面皆已经连通了,一个最小死成树构修完毕.编写本段Kruskal算法的代码真止真代码MST-KRUSKAL(G,w)C代码真止Copyright (c) 2002,2006 by ctu_85All Rights Reserved.*//* I am sorry to say that the situation of unconnected graph is not concerned */#include "stdio.h"#define maxver 10#define maxright 100int G[maxver][maxver],record=0,touched[maxver][maxver]; int circle=0;intFindCircle(int,int,int,int);int main(){int path[maxver][2],used[maxver][maxver];inti,j,k,t,min=maxright,exsit=0;int v1,v2,num,temp,status=0;restart:printf("Please enter the number of vertex(s) in the graph:\n"); scanf("%d",&num);if(num>maxver||num<0){printf("Error!Pleasereinput!\n");goto restart;}for(j=0;j<num;j++)for(k=0;k<num;k++){if(j==k)G[j][k]=maxright;used[j][k]=1;touched[j][k]=0;}elseif(j<k){re:printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);scanf("%d",&temp);if(temp>=maxright||temp<-1){printf("Invalid input!\n");goto re;}if(temp==-1)temp=maxright;G[j][k]=G[k][j]=temp;used[j][k]=used[k][j]=0;touched[j][k]=touched[k][j]=0;}for(j=0;j<num;j++){path[j][0]=0;path[j][1]=0;}for(j=0;j<num;j++){status=0;for(k=0;k<num;k++)if(G[j][k]<maxright){status=1;break;}if(status==0)break;}for(i=0;i<num-1&&status;i++) {for(j=0;j<num;j++)for(k=0;k<num;k++)if(G[j][k]<min&&!used[j][k]){v1=j;v2=k;min=G[j][k];}if(!used[v1][v2]){used[v1][v2]=1;used[v2][v1]=1;touched[v1][v2]=1;touched[v2][v1]=1;path[0]=v1;path[1]=v2;for(t=0;t<record;t++)FindCircle(path[t][0],path[t][0],num,path[t][0]); if(circle){/*if a circle exsits,roll back*/circle=0;i--;exsit=0;touched[v1][v2]=0;touched[v2][v1]=0;min=maxright;}else{record++;min=maxright;}}}if(!status)printf("We cannot deal with it because the graph is not connected!\n");else{for(i=0;i<num-1;i++)printf("Path %d:vertex %d tovertex %d\n",i+1,path[0]+1,path[1]+1);}return 1;}intFindCircle(intstart,intbegin,inttimes,int pre) { /* to judge whether a circle is produced*/ inti;for(i=0;i<times;i++)if(touched[begin]==1){if(i==start&&pre!=start){circle=1;return 1;break;}elseif(pre!=i)FindCircle(start,i,times,begin);elsecontinue;}return 1;}matlab代码真止functionKruskal(w,MAX)%此步调为最小收撑树的Kruskal算法真止%w为无背图的距离矩阵,故为对付称矩阵%MAX为距离矩阵中∞的本质输进值%时间:2011年6月22日0:07:53len=length(w); %图的面数edge=zeros(len*(len-1),3); %用于死存图中的边count=1; %图中的边数for i=1:len-1 %循环距离矩阵,记录死存边for j=i+1:lenif w(i,j)~=MAXedge(count,1)=w(i,j);edge(count,2)=i;edge(count,3)=j;count=count+1;endendendedge=edge(1:count-1,:); %去掉无用边[tmp,index]=sort(edge(:,1)); %所有边按降序排序i=3; %本去尝试边数为3条(3条以下无法形成圈,即无需检测)while 1x=findcycle(edge(index(1:i),:),len); %检测那些边是可形成圈if xindex(i)=0; %若形成圈,则将该边对付应的index项标记表记标帜为0,以便与消elsei=i+1; %若不形成圈,则i加1,加进下一边检测endindex=index(index>0); %将形成圈的边从index中与消ifi==lenbreak; %找到切合条件的面数减一条的边,即找到一个最小收撑树endendindex=index(1:len-1); %截短index矩阵,死存前len-1项%%%%%%%%%%%% 截止隐现%%%%%%%%%%%%%s=sprintf('\n\t%s\t%s\t %s\t','边端面','距离','是可正在最小收撑树');fori=1:count-1edge_tmp=edge(i,:);if ~isempty(find(index==i,1))s_tmp=sprintf('\n \t (%d,%d)\t %d\t %s\t',edge_tmp(2),edge_tmp(3),edge_tmp(1),'√');elses_tmp=sprintf('\n \t (%d,%d)\t %d\t %s\t',edge_tmp(2),edge_tmp(3),edge_tmp(1),'×');ends=strcat(s,s_tmp);enddisp(s);endfunctionisfind=findcycle(w,N)%本步调用于推断所给的边是可形成圈:有圈,返回1;可则返回0%w:输进的边的矩阵%N:本图的面数%本理:不竭与消出现次数小于2的端面地方的边,末尾瞅察是可有边留住len=length(w(:,1));index=1:len;while 1num=length(index); %边数p=zeros(1,N); %用于死存各面的出现的次数(一条边对付应二个端面)for i=1:num %统计各面的出现次数p(w(index(i),2))=p(w(index(i),2))+1;p(w(index(i),3))=p(w(index(i),3))+1;endindex_tmp=zeros(1,num); %记录与消出现次数小于2的端面地方的边的边的下标集中discard=find(p<2); %找到出现次数小于2的端面count=0; %记录结余的边数fori=1:num%推断各边是可有仅出现一次端面——不,则记录其序号于index_tmpif ~(~isempty(find(discard==w(index(i),2),1)) ||~isempty(find(discard==w(index(i),3),1)))count=count+1;index_tmp(count)=index(i);endendif num==count %当不边被被与消时,循环停止index=index_tmp(1:count); %革新indexbreak;elseindex=index_tmp(1:count); %革新indexendendif isempty(index) %若末尾剩下的边数为0,则无圈isfind=0;elseisfind=1;endend%% a =[% 0 3 2 3 100 100100% 3 0 2 100 100100 6% 2 2 0 3 100 1 100% 3 100 3 0 5 100 100% 100 100100 5 0 4 6% 100 100 1 100 4 0 5% 100 6 100 6 100 5 0];%% Kruskal(a,100)pascal代码真止{最小死成树的Kruskal算法.Kruskal算法基础思维:屡屡选不属于共一连通分量(包管不死成圈)且边权值最小的顶面,将边加进MST,并将地方的2个连通分量合并,曲到只剩一个连通分量排序使用Quicksort(O(eloge))查看是可正在共一连通分量用Union-Find,屡屡Find战union运算近似常数Union-Find使用rank开收式合并战路径压缩总搀纯度O(eloge)=O(elogv) (果为e<n(n-1)/2)}constmaxn=100;maxe=maxn*maxn;typeedge=recorda,b :integer; //边的2个顶面len :integer; //边的少度end;varedges :array[0..maxe]of edge; //死存所有边的疑息p,r :array[0..maxn]of integer; //p死存i的女亲节面,r用去真止Union-Find的rank开收式n,e :integer; //n为顶面数,e为边数procedure swap(a,b:integer); //接换beginedges[0]:=edges[a];edges[a]:=edges[b];edges[b]:=edges[0];end;procedure quicksort(l,r:integer); //赶快排序varx,i,j :integer;beginx:=edges[random(r-l+1)+l].len;i:=l;j:=r;repeatwhile edges[i].len<x do inc(i);while edges[j].len>x do dec(j);ifi<=j thenbeginswap(i,j);inc(i);dec(j);enduntili>j;if l<j then quicksort(l,j);ifi<r then quicksort(i,r);end;procedureinit;vari :integer;beginassign(input,'g.in');reset(input);readln(n,e);for i:=1 to e do readln(edges[i].a,edges[i].b,edges[i].len); //从文献读进图的疑息for i:=1 to n do p[i]:=i; //初初化并查集randomize;quicksort(1,e); //使用赶快排序将边按权值从小到大排列end;function find(x:integer):integer; //并查集的Find,用去推断2个顶面是可属于一个连通分量beginif x<>p[x] then p[x]:=find(p[x]);find:=p[x]end;procedure union(a,b:integer); //如果不属于且权值最小则将2个顶面合并到一个连通分量vart :integer;begina:=find(a);b:=find(b);if r[a]>r[b] then begin t:=a;a:=b;b:=t end;if r[a]=r[b]then inc(r[a]);p[a]:=b;end;procedure kruskal; //主历程varen :integer; //en为目前边的编号count :integer; //统计举止了频频合并.n-1次合并后便得到最小死成树tot :integer; //统计最小死成树的边权总战begincount:=0;en:=0; tot:=0;while count<n-1 dobegininc(en);with edges[en] dobeginif find(a)<>find(b) thenbeginunion(a,b);writeln(a,'--',b,':',len);inc(tot,len);inc(count);end;end;end;writeln('Total Length=',tot)end;{===========main==========} begininit;kruskal;end.例题详睹vijos p1045 Kerry 的电缆搜集typerec=recordx,y:longint;cost:real;end;varf:array[1..1000000] of rec;s,ans:real;i,n,m,k,dad:longint;father:array[1..1000000] of longint; procedurekp(l,r:longint);vari,j:longint;xx:real;y:rec;begini:=l;j:=r;xx:=f[(i+j) div 2].cost;repeatwhile xx>f[i].cost do inc(i);while xx<f[j].cost do dec(j);ifi<=j thenbeginy:=f[i];f[i]:=f[j];f[j]:=y;inc(i);dec(j);end;untili>j;ifi<r then kp(i,r);if l<j then kp(l,j);end;function find(x:longint):longint; beginif father[x]=x then exit(x);father[x]:=find(father[x]);exit(father[x]);end;procedure union(x,y:longint;j:real); beginx:=find(x);y:=find(y);if x<>y thenbeginfather[y]:=x;ans:=ans+j;inc(k);end;end;beginreadln(s);readln(n);m:=0;while not eof do begininc(m);with f[m] doreadln(x,y,cost); end;if m<n-1 then beginwriteln('Impossible'); exit;end;fori:=1 to n do father[i]:=i;kp(1,m);k:=0;fori:=1 to m dobeginif k=n-1 then break;union(f[i].x,f[i].y,f[i].cost);end;if k<n-1 thenbeginwriteln('Impossible');exit;end;ifans>s then writeln('Impossible') elsewriteln('Need ',ans:0:2,' miles of cable');end.Kruskal算法适用于边稀稀的情形,而Prim算法适用于边稀稀的情形其余最小死成树算法c++代码真止#include <stdio.h>#include <stdlib.h>#include <vector>using namespace std;#define MAXNUM_VERTEX 20 //最多有20个顶面#define MAXNUM_EDGE 21typedefstruct{intv,w;int weight;}Edge;typedefstruct{int vertex[MAXNUM_VERTEX];Edge edge[MAXNUM_EDGE];intnum_vertex,num_edge;}Graph;Graph graph; //声明为齐部变量boolsearch_vertex(intver){for(inti=0; i<graph.num_vertex; i++)if(ver == graph.vertex[i] )return 1;printf("the vertex %d you input is not existed! \n",ver); return 0;}voidcreate_graph(){//输进顶面疑息printf("input the number of vertex in the graph\n");scanf(" %d",&graph.num_vertex);printf("input the vertex of graph,like 1,2\n");for(inti=0; i<graph.num_vertex; i++)scanf(" %d",&graph.vertex[i]);//输进边疑息printf("input the number of edge in the graph\n");scanf(" %d",&graph.num_edge);printf("intput the edge of graph and the weight of line,like 1-2 5\n");for(int j=0; j<graph.num_edge; j++){p1:inta,c,d;char b;scanf(" %d %c %d %d",&a,&b,&c,&d);if(search_vertex(a) && search_vertex(c) ){graph.edge[j].v=a;graph.edge[j].w=c;graph.edge[j].weight=d;}elsegoto p1;}}voidsort_by_weight(){for(inti=1; i<graph.num_edge; i++){Edge temp=graph.edge[i];for(int j=i-1; j>=0 && graph.edge[j].weight>temp.weight; j--) graph.edge[j+1]=graph.edge[j];graph.edge[j+1]=temp;}}/*不相接集处理函数*/inline void makeset(vector<int> & array){for(inti=0; i<array.size(); i++)array[i]=i;}intfindset(vector<int> & parent,inti){if(i != parent[i])i=parent[i];returni;}inline void merge(vector<int> & parent,inti,int j) {parent[i]=j;}/*不相接集处理函数*/voidkruskal(){intnum_ver=graph.num_vertex;int count=0;vector<int> parent_ver;parent_ver.resize(num_ver);/*核心部分是用不相接集中成树*/ makeset(parent_ver);printf("the edge of min tree as follow: \n");for( inti=0; i<num_ver && count<num_ver-1; i++ ) //count 表示合并(merge)的次数num_ver-1次{int m=graph.edge[i].v;int n=graph.edge[i].w;int w=graph.edge[i].weight;if(findset(parent_ver,m) != findset(parent_ver,n)) //当属于分歧的集中时,则将该边增加进树中{printf("(%d %d) %d\n",m,n,w);merge(parent_ver,m,n);count++;}}}voidprint_edge(){printf("the graph you input as follow: \n");for(inti=0; i<graph.num_edge; i++)printf("%d-%d the weightis: %d\n",graph.edge[i].v,graph.edge[i].w,graph.edge[i].weight);}void main(){create_graph();sort_by_weight();print_edge();kruskal();}java代码真止importjava.util.ArrayList;importjava.util.Collections;class Bian implements Comparable // 二面之间的加权边{private intfirst,second;// 表示一条边的二个节面private int value;// 权值publicBian(intfirst,intsecond,int value) {this.first = first;this.second = second;this.value = value;}publicintgetFirst() {return first;}publicintgetSecond() {return second;}publicintgetValue() {return value;}@OverridepublicintcompareTo(Object arg0) {return value > ((Bian) arg0).value 1: (value == ((Bian) arg0).value 0 : -1);}@Overridepublic String toString() {return "Bian [first=" + first + ",second=" + second + ",value="+ value + "]";}}classShuZu {static ArrayList<ArrayList> list = newArrayList<ArrayList>();// 存搁每一个数组中的节面的数组static ArrayList<ArrayList> bianList = newArrayList<ArrayList>();// 对付应存搁数组中的边的数组public static void check(Bian b)// 查看正在哪个数组中{if (list.size() == 0) {ArrayList<Integer> sub = new ArrayList<Integer>();sub.add(b.getFirst());sub.add(b.getSecond());list.add(sub);ArrayList<Bian> bian = new ArrayList<Bian>();bian.add(b);bianList.add(bian);return;}int first = b.getFirst();int shuyu1 = -1;int second = b.getSecond();int shuyu2 = -1;for (inti = 0; i < list.size(); i++)// 查看二个节面分别属于哪个数组{for (int m = 0; m < list.get(i).size(); m++) {if (first == (Integer) list.get(i).get(m))shuyu1 = i;if (second == (Integer) list.get(i).get(m))shuyu2 = i;}}if (shuyu1 == -1 && shuyu2 == -1)// 表示那二个节面皆不需要新加进{ArrayList<Integer> sub = new ArrayList<Integer>();sub.add(b.getFirst());sub.add(b.getSecond());list.add(sub);ArrayList<Bian> bian = new ArrayList<Bian>();bian.add(b);bianList.add(bian);}if (shuyu1 == -1 && shuyu2 != -1)// 表示有一个面已经正在数组中只把另一个加进便不妨了{list.get(shuyu2).add(first);bianList.get(shuyu2).add(b);}if (shuyu2 == -1 && shuyu1 != -1)// 表示有一个面已经正在数组中只把另一个加进便不妨了{list.get(shuyu1).add(second);bianList.get(shuyu1).add(b);}if (shuyu1 == shuyu2 && shuyu1 != -1)// 表述二个正在共一个组中会产死环{}if (shuyu1 != shuyu2 && shuyu1 != -1 && shuyu2 != -1)// 表示二个面正在分歧的组中需要合并{for (inti = 0; i < list.get(shuyu2).size(); i++) {list.get(shuyu1).add(list.get(shuyu2).get(i));}list.remove(shuyu2);for (inti = 0; i < bianList.get(shuyu2).size(); i++) { bianList.get(shuyu1).add(bianList.get(shuyu2).get(i));}bianList.get(shuyu1).add(b);bianList.remove(shuyu2);}}public static void show() {for (inti = 0; i < bianList.get(0).size(); i++) System.out.println(bianList.get(0).get(i));}}public class Test {public static void main(String[] args) { ArrayList<Bian> l = new ArrayList<Bian>(); l.add(new Bian(1,3,1));l.add(new Bian(1,2,6));l.add(new Bian(1,4,5));l.add(new Bian(2,3,5));l.add(new Bian(2,5,3));l.add(new Bian(3,4,5));l.add(new Bian(3,5,6));l.add(new Bian(3,6,4));l.add(new Bian(4,6,2));l.add(new Bian(5,6,6));Collections.sort(l);// for(inti = 0 ;i<l.size();i++)// System.out.println(l.get(i)); for (inti = 0; i < l.size(); i++) ShuZu.check(l.get(i));ShuZu.show();}}。

shortestpathtree matlab 函数

shortestpathtree matlab 函数

shortestpathtree matlab 函数矩阵中的所有节点之间都有一些路径连接着。

某些路径可能是直接的,而有些可能需要经过其他节点。

寻找从一个节点到另一个节点的最短路径是图论中一个经典的问题。

在 MATLAB 中,可以使用 shortestpathtree 函数来解决这个问题。

首先,让我们了解一下最短路径树(Shortest Path Tree)是什么。

最短路径树是一个有向图,它以某个源节点为根节点,并将所有其他节点连接到根节点的最短路径。

最短路径树通常用于网络中的路由选择和通信网络中的拓扑控制。

在 MATLAB 中,你可以使用 shortestpathtree 函数来计算具有有向边的有向图的最短路径树。

这个函数采用一个邻接矩阵作为输入,并返回一个有向图的最短路径树。

邻接矩阵是一个 N×N 的矩阵,其中 N 是图中节点的数量。

邻接矩阵的第 i 行第 j 列的元素表示从节点 i 到节点 j 是否有一条边。

如果有边连接,则该元素的值为非零,否则为零。

在有向图中,边是有方向的,所以邻接矩阵是对称的。

为了使用 shortestpathtree 函数,我们首先需要创建一个邻接矩阵。

我们可以使用 MATLAB 中的矩阵操作来实现这一点。

例如,我们可以使用 zeros 函数创建一个全零矩阵,然后使用索引操作将适当的元素设置为非零值,从而表示边的存在。

例如,假设我们有一个图,其中有四个节点,从节点 1 到节点 3 有一条权重为2 的边,从节点 1 到节点 4 有一条权重为 5 的边,从节点 2 到节点 3 有一条权重为 1 的边,从节点 2 到节点 4 有一条权重为 3 的边。

我们可以通过以下方式创建邻接矩阵:matlabadjacency_matrix = zeros(4);adjacency_matrix(1, 3) = 2;adjacency_matrix(1, 4) = 5;adjacency_matrix(2, 3) = 1;adjacency_matrix(2, 4) = 3;现在我们已经创建了邻接矩阵,我们可以使用 shortestpathtree 函数来计算最短路径树。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

function [Wt,Pp]=mintree(n,W)
%求最小生成树,n为顶点个数,W就是权值邻接矩阵,不相邻的用inf表示%Wt就是最小生成树的权,Pp(:,1:2)表示最小生成树的两顶点
%Pp(:,4)表示最小生成树的序号
tmpa=find(W~=inf);
[tmpb,tmpc]=find(W~=inf);
w=W(tmpa);
e=[tmpb,tmpc];
[wa,wb]=sort(w);
E=[e(wb,:),wa,wb];
[nE,mE]=size(E);
temp=find(E(:,1)-E(:,2));
E=E(temp,:);
P=E(1,:);
k=length(E(:,1));
while rank(E)>0
temp1=max(E(1,2),E(1,1));
temp2=min(E(1,2),E(1,1));
for i=1:k
if E(i,1)==temp1
E(i,1)=temp2;
end
if E(i,2)==temp1
E(i,2)=temp2;
end
end
a=find(E(:,1)-E(:,2));
E=E(a,:);
if rank(E)>0
P=[P;E(1,:)];
k=length(E(:,1));
end
end
Wt=sum(P(:,3));
Pp=[e(P(:,4),:),P(:,3:4)];
for i=1:length(P(:,3))
disp(['','e',num2str(P(i,4)),'',、、、
'(v',num2str(P(i,1)),'','v',num2str(P(i,2)),')']);
end
axis equal;%画最小生成树
hold on
[x,y]=cylinder(1,n);
xm=min(x(1,:));
ym=min(y(1,:));
xx=max(x(1,:));
yy=max(y(1,:));
axis([xm-abs(xm)*0、15,xx+abs(xx)*0、15,ym-abs(ym)*0、15,yy+abs(yy)*0、15]); plot(x(1,:),y(1,:),'ko');
for i=1:n
temp=['v',int2str(i)];
text(x(1,i),y(1,i),temp);
end
for i=1:nE
plot(x(1,e(i,:)),y(1,e(i,:)),'b');
end
for i=1:length(P(:,4))
plot(x(1,Pp(i,1:2)),y(1,Pp(i,1:2)),'r');
end
text(-0、35,-1、2,['最小生成树的权为','',num2str(Wt)]);
title('红色连线为最小生成树');
axis off;
hold off;
调用此程序要先编写主程序。

例:
n=6;
W=inf*ones(6);
W(1,[2,3,4])=[6,1,5];
W(2,[3,5])=[5,3];
W(3,[4,5,6])=[5,6,4];
W(4,6)=2;
W(5,6)=6;
[a,b]=mintree(n,W)
命名为example
在窗口中运行此程序得:
e2(v1v3)
e9(v4v6)
e6(v2v5)
e8(v1v4)
e3(v2v1)
a =
15
b =
1 3 1 2
4 6 2 9
2 5
3 6
3 6
4 8
2 3 5 3。

相关文档
最新文档