算法-21-最短路径(Dijkstra+最优算法+Bellman-Ford)

目录

1、定义

1.1、性质

2、数据结构

2.1、有向边的代码

2.2、加权有向的图的代码

3、核心思想

4、Dijkstra算法

5、求最短路径的最优算法

6、通用最短路径算法---Bellman-Ford


1、定义

我们生活中经常会使用地图来查找我们到达目的的路线,而我们希望每次走的都是最短路线,而我们这一节将要学习的就是在一个图中,寻找a点到b点的最短路径。

最短路径: 找到从一个顶点到达另一个顶点的成本最小的路径。

1.1、性质

这里我们使用加权有向图的模型来学习计算最短路径的方法。加权就是在两个顶点之间的边上加上权重,这样我们不仅要找到从a点到b点的路径,还要找到权值最小的那一条。

下图就是一个加权有向图:从0点到6点的最短路径就是0-->2-->7-->3-->6 ,权值之和最小等于:1.51

我们在利用加权有向图模型去求最短路径的时候,需要注意以下几点:

  1. 路径是有向的。
  2. 权重不一定等价于边的长短。
  3. 并不是所有点都是可达的,如果a点到b点没有可达的路径,那么就不存在最短路径,我们后面学习的算法都将建立在这个图所有点都是可达的情况下。
  4. 边的负权重将会是计算最短路径变得非常麻烦。
  5. 最短路径不一定是唯一的,可能有多条,我们只找到一条就行。

2、数据结构

这里我们的加权有向图在上一节加权无向图的基础上进行一定修改,就可以得到保存加权有向图的数据类型。

DirectedEdge类来存储边、边的权值、边的两个顶点。

EdgeWeightedDigraph 类 中有一个 数据链表,数组用来存储每个顶点,链表用来存储每个顶点指向的边。

2.1、有向边的代码

public class DirectedEdge {
    private final int v;            // 边的起点
    private final int w;            // 边的终点
    private final double weight;    // 边的权重

    public DirectedEdge(int w, int v, double weight) {
        this.w = w;
        this.v = v;
        this.weight = weight;
    }

    public int from() {
        return v;
    }
    public int to() {
        return w;
    }
    public double weight() {
        return weight;
    }
}

2.2、加权有向的图的代码

public class EdgeWeightedDigraph {

    private final int V; // 顶点的数量
    private int E; // 边的数量
    private final Bag<DirectedEdge>[] adj; // 邻接表

    public EdgeWeightedDigraph(int v) {
        V = v;
        adj = new Bag[v];
        for (int i = 0; i < v; i++) {
            adj[i] = new Bag<>();
        }
    }
    /**
     * 将边添加到 邻接表中
     */
    public void addEdge(DirectedEdge edge) {
        int v = edge.from();
        adj[v].add(edge);
        E++;
    }
    public int V() {
        return V;
    }
    public int E() {
        return E;
    }
    public Iterable<DirectedEdge> adj(int v){
        return adj[v];
    }
    /**
     * 将有向图中的所有边都存储到一个Bag中并返回
     */
    public Iterable<DirectedEdge> edges(){
        Bag<DirectedEdge> edges=new Bag<>();
        
        for (int i=0;i<V;i++){
            for (DirectedEdge e:adj[i]){
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值