Dijkstra 算法 Java实现

最近看文章看到Dijkstra 算法,想起大学的时候学习的算法导论这门课程

突然就想用java来实现下这个算法了,

以下就来介绍一下这个算法吧.

Dijkstra 算法主要是用来解决有向图单个点到其他点的最短路径的问题

然后我根据这个有向图来编写了Dijkstra 算法

这里写图片描述

public static void main(String[] args) {
        //定义一个有向图
        //定义一个集合,所有点的集合
        List<String> DOT=new ArrayList<>();
        DOT.add("A");
        DOT.add("B");
        DOT.add("C");
        DOT.add("D");
        DOT.add("E");
        DOT.add("F");
        DOT.add("G");
        //定义一个集合,所有边到边的距离
        Map<String,Integer> EGED=new HashMap<>();
        EGED.put("AB",8);
        EGED.put("AE",4);
        EGED.put("AF",2);
        EGED.put("BA",8);
        EGED.put("BE",7);
        EGED.put("BC",6);
        EGED.put("CB",6);
        EGED.put("CD",6);
        EGED.put("DC",6);
        EGED.put("DE",9);
        EGED.put("DG",7);
        EGED.put("EA",4);
        EGED.put("EB",7);
        EGED.put("ED",9);
        EGED.put("EG",11);
        EGED.put("EF",3);
        EGED.put("FA",2);
        EGED.put("FE",3);
        EGED.put("FG",5);
        EGED.put("GE",11);
        EGED.put("GF",5);
        EGED.put("GD",7);
        //创建一个被选中的点的集合
        LinkedList<String> choose=new LinkedList<>();
        String Next=loop("A",DOT,choose,EGED);
        String Next1=loop(Next,DOT,choose,EGED);
        String Next2=loop(Next1,DOT,choose,EGED);
        String Next3=loop(Next2,DOT,choose,EGED);
        String Next4=loop(Next3,DOT,choose,EGED);
        String Next5=loop(Next4,DOT,choose,EGED);
        System.out.println("A"+"---"+Next+"---"+Next1+"---"+Next2+"---"+Next3+"---"+Next4+"---"+Next5);
    }

    public static String loop(String startPot,List DOT,List choose,Map<String,Integer> EGED){
        //把起始点放入,这里我们选择A
        choose.add(startPot);
        DOT.remove(startPot);
        //在边的集合中找到A开始的边
        System.out.println(EGED.entrySet());
        Map<String,Integer> map=new HashMap<>();
        for (String s:EGED.keySet()) {
            String TheKey=findroad(s,startPot+"\\w");
            if (!("").equals(TheKey))
            {
                if (map.isEmpty())
                {
                    map.put(TheKey,EGED.get(TheKey));
                }else{

                    if (map.values().iterator().next()>EGED.get(TheKey)){
                        map.clear();
                        map.put(TheKey,EGED.get(TheKey));
                    }
                }
            }
        }
        String Next="";
        System.out.println(map.entrySet());
        for (String s:map.keySet()) {
            Next=s.substring(1);
        }
        System.out.println(Next);
        //找到最短路径之后就把所有和这个点相关的路径删除
        List a=new ArrayList<>();
        for (String sD:EGED.keySet()) {
            String TheKey=findroad(sD,"\\w*"+startPot+"\\w*");
            if (!("").equals(TheKey))
            {
                a.add(TheKey);
            }
        }
        for (int i = 0; i < a.size(); i++) {
            EGED.remove(a.get(i));
        }
        System.out.println(EGED.entrySet());
        return Next;
    }
    public static String findroad(String bian,String regEx){
        Pattern pattern=Pattern.compile(regEx);
        Matcher matcher=pattern.matcher(bian);
        if (matcher.find())
        {
            return bian;
        }else{
            return "";
        }
    }

以上是代码
以下是运行输出

[GD=7, FA=2, GE=11, GF=5, EA=4, FE=3, EB=7, ED=9, DC=6, CB=6, BA=8, AB=8, BC=6, AE=4, AF=2, BE=7, CD=6, DE=9, EG=11, EF=3, DG=7, FG=5]
[AF=2]
F
[GD=7, GE=11, GF=5, FE=3, EB=7, ED=9, DC=6, CB=6, BC=6, BE=7, CD=6, DE=9, EG=11, EF=3, DG=7, FG=5]
[GD=7, GE=11, GF=5, FE=3, EB=7, ED=9, DC=6, CB=6, BC=6, BE=7, CD=6, DE=9, EG=11, EF=3, DG=7, FG=5]
[FE=3]
E
[GD=7, GE=11, EB=7, ED=9, DC=6, CB=6, BC=6, BE=7, CD=6, DE=9, EG=11, DG=7]
[GD=7, GE=11, EB=7, ED=9, DC=6, CB=6, BC=6, BE=7, CD=6, DE=9, EG=11, DG=7]
[EB=7]
B
[GD=7, DC=6, CB=6, BC=6, CD=6, DG=7]
[GD=7, DC=6, CB=6, BC=6, CD=6, DG=7]
[BC=6]
C
[GD=7, DC=6, CD=6, DG=7]
[GD=7, DC=6, CD=6, DG=7]
[CD=6]
D
[GD=7, DG=7]
[GD=7, DG=7]
[DG=7]
G
[]
A---F---E---B---C---D---G

这是初版吧…没时间了..有时间在update一下,

其实dijkstra 算法的核心就是,在一堆有向图中,找一个起始点,然后查看和该点的连接中,最小的那个点,当作下一个起始点, 在本例中,A是出发点,第一次调用该循环的时候,AF-2是最小的,数值是2,所以F点是第二遍的起始点,但是我们已经用过了A,所以在下次循环里面的与A点相关的点我们都给删除掉,在进行循环,当边的那个集合为空时就给退出循环,路径也就找出来了.
当然,本文是最基础的实现,很多东西没考虑好,比如,很多个点怎么办,大量数据的时候怎么办,这么多循环的效率肯定非常低,
欢迎大家给建议,来提升该算法的性能,哈哈哈哈.
以上
2017-2-23

Dijkstra算法是一种用于寻找图中两点之间最短路径的贪心算法,通常用于解决单源最短路径问题。在Java实现Dijkstra算法,你可以按照以下步骤进行: 1. 初始化:创建一个优先队列(通常使用`PriorityQueue`或自定义最小堆),存储顶点和它们的距离(初始时距离为无穷大,源节点距离为0)。 2. 创建邻接表或邻接矩阵表示图。 3. 主循环: a. 从队列中取出当前最短距离的节点。 b. 更新与其相邻节点的距离,如果通过当前节点到达更短,更新距离,并标记该节点已访问。 c. 将未访问的邻居节点加入队列。 4. 当队列为空或找到目标节点时,算法结束。此时队列中的最后一个元素即为目标节点,且所有节点的距离值即是最短路径。 以下是简单的Java代码实现: ```java import java.util.*; public class Dijkstra { private final int V; // 图的顶点数 private List<List<Edge>> adj; // 邻接列表 private int[] dist; // 存储每个节点到源的距离 // 边类,包含起点、终点和权重 class Edge implements Comparable<Edge> { int src, dest, weight; public Edge(int src, int dest, int weight) { this.src = src; this.dest = dest; this.weight = weight; } @Override public int compareTo(Edge other) { return Integer.compare(this.weight, other.weight); } } public Dijkstra(int v, List<List<Edge>> adj) { this.V = v; this.adj = adj; dist = new int[V]; Arrays.fill(dist, Integer.MAX_VALUE); dist = 0; } // Dijkstra算法核心部分 public void dijkstra() { PriorityQueue<Edge> pq = new PriorityQueue<>(); pq.add(new Edge(0, 0, 0)); // 元素为 (距离, 节点, 来源) while (!pq.isEmpty()) { Edge curr = pq.poll(); int u = curr.dest; // 当前节点 if (dist[u] < curr.weight) continue; // 已经找到更短路径,跳过 for (Edge e : adj.get(u)) { int v = e.dest, alt = dist[u] + e.weight; if (alt < dist[v]) { dist[v] = alt; pq.removeIf(edge -> edge.src == v); // 如果找到更短路径,移除旧路径 pq.offer(new Edge(v, alt, u)); // 添加新路径 } } } } // 返回源节点到所有其他节点的最短距离 public int[] printDistances() { return dist; } // 示例用法 public static void main(String[] args) { List<List<Edge>> adj = new ArrayList<>(); // 图的邻接列表构建 // 填充邻接列表... Dijkstra dijkstraAlg = new Dijkstra(V, adj); dijkstraAlg.dijkstra(); int[] shortestDist = dijkstraAlg.printDistances(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值