单源最短路径(Dijkstra算法)(Java)

单源最短路径中的Dijkstra算法属于贪心算法,它的图中不允许出现权重为负值的边
算法解决的是带权重的有向图中单源最短路径问题。
算法时间复杂度与所用的优先队列的实现有关。算法与图的深度优先遍历(DFS)和最小生成树的Prim算法相似,尤其与Prim相似
详细介绍可看《算法导论》第24章,下面的链接是别人的介绍与C代码
别人的介绍与C代码
Java代码如下,图是由邻接链表实现的

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;


public class Test {

    public static void main(String[] args) {
        //构建有向图
        Map<V, List<V>> G = new HashMap<>();
        V s = new V('s');
        V t = new V('t');
        V y = new V('y');
        V x = new V('x');
        V z = new V('z');
        List<V> sN = new LinkedList<>();	sN.add(t);sN.add(y);
        List<V> tN = new LinkedList<>();	tN.add(x);tN.add(y);
        List<V> yN = new LinkedList<>();	yN.add(t);yN.add(x);yN.add(z);
        List<V> xN = new LinkedList<>();	xN.add(z);
        List<V> zN = new LinkedList<>();	zN.add(s);zN.add(x);
        G.put(s, sN);
        G.put(t, tN);
        G.put(x, xN);
        G.put(y, yN);
        G.put(z, zN);
        //储存所有边的集合
        List<Edge> alledges = new ArrayList<>();
        alledges.add(new Edge(s, t, 10));
        alledges.add(new Edge(s, y, 5));
        alledges.add(new Edge(t, x, 1));
        alledges.add(new Edge(t, y, 2));
        alledges.add(new Edge(x, z, 4));
        alledges.add(new Edge(y, t, 3));
        alledges.add(new Edge(y, x, 9));
        alledges.add(new Edge(y, z, 2));
        alledges.add(new Edge(z, s, 7));
        alledges.add(new Edge(z, x, 6));

        DijkstraSPath(G, alledges,s);
    }

    public static void DijkstraSPath(Map<V, List<V>> G, List<Edge> alledges, V s) {
        s.d = 0;//源点到自己的距离为0
        PriorityQueue<V> Q = new PriorityQueue<>((v1, v2)-> {return v1.d - v2.d;});//要给优先队列传比较器
        Q.addAll(G.keySet());

        while(!(Q.isEmpty())) {
            V u = Q.poll();//取出当前离源点最近的点
            for(V v : G.get(u)) {//更新所有邻点的值
                int w = Integer.MAX_VALUE;
                for(Edge edge : alledges)
                    if((edge.s.equals(u) && edge.d.equals(v))||(edge.d.equals(u) && edge.s.equals(v)))
                        w = edge.w;
                if(v.d > u.d + w) {
                    v.d = u.d + w;
                    Q.remove(v);//优先队列自己无法更新,要变动它才会
                    Q.add(v);
                    v.p = u;
                }
            }
        }
        
        for(V key : G.keySet())
            System.out.println("经过DijkstraSPath算法后," + key + "距s节点的距离为" + key.d);
    }
}

//结点类
class V {
    char name;//结点名
    int d;//记录该点到源点的路径,初始值为无限大
    V p;//父节点,即算法中到这个点的最短路径的上一个点

    public V(char name) {
        this.name = name;
        d = Integer.MAX_VALUE;
        p = null;
    }

    public int hashCode() {//hashmap必须重写
        return name;
    }

    public boolean equals(Object o) {//hashmap必须重写
        if(!(o instanceof V))
            return false;
        if(o == this)
            return true;
        return name == ((V)o).name;
    }

    public String toString() {
        return "" + name;
    }
}

//边类
class Edge {
    V s;//s与d代表边的2个端点
    V d;
    int w;//边的权重

    public Edge(V s, V d, int w) {
        this.w = w;
        this.s = s;
        this.d = d;
    }

    public String toString() {
        return s + "-" + d + " " + w;
    }

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值