算法2—图与网络模型及方法(一)


前言

解决最短路径问题首先了解如下概念:

图的基本概念

1.无向图概念

在这里插入图片描述

2.有向图概念

在这里插入图片描述

3. 完全图、二分图

完全图:指图的两顶点间有边相连,两顶点相邻,顶点都相邻的图称为完全图。
在这里插入图片描述
简单图:任两点间最多有一条边,且每条边的两个端点都不重合的图称为简单图。

4.子图、顶点的度

图 H 叫做图 G 的子图(subgraph),记作 H ⊂ G ,如果 V (H ) ⊂V (G) , E(H) ⊂ E(G) 。若 H 是G 的子图,则G 称为 H 的母图。 G 的支撑子图(spanning subgraph,生成子图)是指满足V(H) =V(G) 的子 图 H 。
顶点的度:设v ∈V (G) ,G 中与v 关联的边数(每个环算作两条边)称为v 的度(degree),记 作d(v)。若d(v)是奇数,称v 是奇顶点(odd point);d(v)是偶数,称v 是偶顶点(even point)。
(i)
在这里插入图片描述

(ii) 任意一个图的奇顶点的个数是偶数。

图与网络的数据结构

首先假设 G = (V, A)是一个简单有向图,顶点集合V={v1,v2,…,vn},边集E={e1,…,en},记|V |= n,| E|= m 。

1.邻接矩阵

在这里插入图片描述
采用邻接矩阵表示图,直观方便,通过查看矩阵中的元素就可以判断任意两点之间是否有边,以及边上的值。

  • 例题
    图 2 所示的有向图,可以用邻接矩阵表示为

在这里插入图片描述在这里插入图片描述

2.稀疏矩阵
  • 对于有向图的邻接矩阵转化为稀疏矩阵
    S = sparse(A)
    将矩阵A转化为稀疏矩阵形式,即矩阵A中任何0元素被去除,⾮零元素及其下标组成矩阵S。如果A本⾝是稀疏的,sparse(S)返回S。
  • 对于无向图地的邻接矩阵转化为稀疏矩阵
    由于邻接矩阵是对矩阵,Matlab中只需要使用邻接矩阵的下三角元素,即Matlab只储存邻接矩阵下三角元素中的非零元素。
  • 稀疏矩阵转化为普通矩阵
    A=full(S)
    把稀疏矩阵S转换为全矩阵存储形式A
  • Matlab工具的使用
    在这里插入图片描述

一、Dijkstra算法解决两个指定顶点之间的最短路径问题。

问题如下:给出了一个连接若干个城镇的铁路网络,在这个网络的两个指定城镇间, 找一条最短铁路线。
在这里插入图片描述
Dijkstra算法 :
在这里插入图片描述

  • 例题1
    某公司在六个城市c(1),c(2),…,c(6) 中有分公司,从 c(i))到 c(j) 的直接航程票价记在如下矩阵的 ( i,j ) 位置上(∞表示无直接航路)。请帮助该公司设计一张城市 c(1)到其它城市间的票价最便宜的路线图。
    在这里插入图片描述
    用矩阵 a(nxn) (n为顶点个数)存放各边权的邻接矩阵,行向量pb, index(1), index(2) , d 分别用来存放P 标号信息、标号顶点顺序、标号顶点索引、短通路的值。其中分量为
    在这里插入图片描述
    第一个城市到其他城市的最短路径。
clc,clear
a=zeros(6); % 邻接矩阵初始化
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;
a(2,3)=15;a(2,4)=20;a(2,6)=25;
a(3,4)=10;a(3,5)=20;
a(4,5)=10;a(4,6)=25;
a(5,6)=55;
a=a+a';
a(find(a==0))=inf; % 将零元素替换成无穷
pb(1:length(a))=0;pb(1)=1;index1=1;index2=ones(1,length(a));
d(1:length(a))=inf;d(1)=0; % 最短路径的值初始化
temp=1; % 最新的p标号的顶点
while sum(pb)<length(a)
    tb=find(pb==0);
    d(tb)=min(d(tb),d(temp)+a(temp,tb));
    tmpb=find(d(tb)==min(d(tb)));
    temp=tb(tmpb(1)); % 可能有多个点同时到达最小值,只取其中一个
    pb(temp)=1;
    index1=[index1,temp];
    temp2=find(d(index1)==d(temp)-a(temp,index1));
    index2(temp)=index1(temp2(1)); % 存放初始到i顶点中,第i顶点前一顶点
end
d, index1, index2

输出为

d =

     0    35    45    35    25    10


index1 =

     1     6     5     2     4     3


index2 =

     1     6     5     6     1     1

二、两个指定顶点之间的最短路径问题的数学规划模型

在这里插入图片描述

在这里插入图片描述

三、Floyd算法解决每对顶点之间的最短路径

Floyd算法为:
在这里插入图片描述

  • 用Floyd算法解决上述例题1
    1.矩阵path用来存放每对顶点之间最短路径上所经过的顶点的序号。
clear;clc; 
n=6; a=zeros(n); 
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10; 
a(2,3)=15;a(2,4)=20;a(2,6)=25; 
a(3,4)=10;a(3,5)=20; 
a(4,5)=10;a(4,6)=25; 
a(5,6)=55; 
a=a+a'; 
a(a==0) = inf; % 把所有零元素替换成无穷
a([1:n+1:n^2]) = 0; % 对角元素替换成零,Matlab中数据是逐列来存储
path=zeros(n); % 初始panth为零矩阵
for k=1:n  % 中间节点k从1- n 循环   
    for i=1:n % 起始节点i从1- n 循环    
        for j=1:n % 终点节点j从1-n 循环          
            if a(i,j)>a(i,k)+a(k,j)  % 如果i,j两个节点间的最短距离大于i和k的最短距离+k和j的最短距离
                a(i,j)=a(i,k)+a(k,j); 
                path(i,j)=k; % 起点为i,终点为j的两个节点之间的最短路径要经过的节点更新为path(i,k)  
             end 
         end 
     end 
end
path

输出为


path =

     0     6     5     5     0     0
     6     0     0     0     4     0
     5     0     0     0     0     4
     5     0     0     0     0     0
     0     4     0     0     0     1
     0     0     4     0     1     0

2.起点sb到终点db通用的Floyd算法

clc,clear
function [dist,mypath] = myfloyd(a,sb,db)
% dist表示最短路的距离;mypath表示最短的路径
% a表示邻接矩阵;a(i,j)表示顶点i到j之间的直达距离,可以是有向的
% sb是起点标号;db是终点的标号
n = size(a,1);
path = zeros(n);
for k=1:n    
    for i=1:n       
        for j=1:n          
            if a(i,j)>a(i,k)+a(k,j)  % 开始迭代
                a(i,j)=a(i,k)+a(k,j); 
                path(i,j)=k;  
             end 
         end 
     end 
end
dist = a(sb,db);
parent = path(sb,:); % 从起点到终点的最短路上各顶点的前驱顶点
parent(parent==0) = sb; % path中的分量为0,表示该点的前驱是起点
mypath = db;t = db;
while t ~= sb
    p = parent(t);mypath = [p,mypath];
    t = p;
end
end

总结

  • Dijkstra算法和Floyd算法详细使用
  • 它们区别在:
    1.Dijkstra不能处理负权图,Flyod能处理负权图。
    2.Dijkstra处理单源最短路径而Flyod是处理多源最短路径。
    3.Dijkstra时间复杂度为O(n^2), Flyod时间复杂度为O(n^3) 空间复杂度为O(n ^ 2);
    如果题目中是单源点正权图,就用Dijkstra算法,如果是任意两个点之间的最短路径或者是负权图,就用Floyd。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白只对大佬的文章感兴趣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值