算法导论——24.3 Dijkstra最短路径算法java实现

2024-03-30 04:48

本文主要是介绍算法导论——24.3 Dijkstra最短路径算法java实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

迪杰斯特拉算法是由荷兰计算机科学家 狄克斯特拉于1959 年提出的,因此又叫 狄克斯特拉算法。是从一个顶点到其余各顶点的 最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
Dijkstra算法是典型的 算法。 Dijkstra算法是很有代表性的 算法。Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用 OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。

适用条件&范围

1. 单源最短路径(从源点s到其它所有顶点v);
2.有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图);
3.边权非负;
4. 差分约束系统;

算法描述


时间复杂度

邻接矩阵 O(n^2)
邻接表 O(n^2)
邻接表+binary heap O((n+m)logn)
邻接表+fibonacci heap O(m+nlogn)


Java代码实现

package algorithms;import util.AlgoGraph;import java.util.Stack;/*** Created with IntelliJ IDEA.* Created by The_Sam on 2017/5/8 22:08*/
public class Dijkstra extends ShortestAlgorithms {private Stack<Integer> Dealing ;private boolean Dealed[];public static void main(String[] args) {ShortestAlgorithms dk = new Dijkstra();System.out.println(dk.analyse(AlgoGraph.defaultMap4()));}boolean analyse(AlgoGraph algoGraph) {ini(algoGraph);int edgenum = algoGraph.getEdgenum();while (!Dealing.empty()) {int i=Dealing.pop();Dealed[i]=true;for (int j = 0; j < edgenum; j++) {//这里以枚举边的方式找以i为u的边,或许还有更好的做法,比如邻接表的形式int u = algoGraph.edge.get(j).u;if (i != u) continue;int v = algoGraph.edge.get(j).v;int cost = algoGraph.edge.get(j).cost;if (dis[v] > dis[u] + cost) {dis[v] = dis[u] + cost;pre[v] = u;if(!Dealed[v])Dealing.push(v);}}}return true;}void ini(AlgoGraph algoGraph) {int nodenum = algoGraph.getNodenum();//初始化,将dis[s]设为0,其他的都设为无限大dis = new int[nodenum];//dis[i] 为 i点到s的最短距离pre = new int[nodenum];//pre[i] 为i搭配s的最短距离的上一个节点Dealed =new boolean[nodenum];Dealing=new Stack<Integer>();int s = algoGraph.getOriginal();//原点Dealing.push(s);for (int i = 0; i < nodenum; i++) {dis[i] = i == s ? 0 : MAXN;}}
}


AlgoGraph.java 表示图的代码附上
package util;import lombok.Getter;
import lombok.Setter;import java.util.ArrayList;/*** Created by The_Sam on 2017/5/8.* 图是从0到nodenum-1表示相应节点*/
public class AlgoGraph {@Getter@Setterprivate int original;@Getter@Setterprivate int nodenum;private int indegrees[];//    private int indegrees[];//indegree[i]表示i节点的入度public ArrayList<AlgoEdge> edge;public int getEdgenum() {return edge.size();}public AlgoGraph(int original, int nodenum, ArrayList<AlgoEdge> edge) {this.original = original;this.nodenum = nodenum;this.edge = edge;}/*** @Description :返回函数各个节点的入度* @Author : The_Sam* @Datetime : 2017/5/8 23:04* @Params :* @Return : int[]*/public int[] getIndegrees() {indegrees=new int[nodenum];for (AlgoEdge e :edge) {indegrees[e.v]++;}return indegrees;}/*** @Description: 返回一个图,为算法导论图24-4,带负权无负权回路有向环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap1() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, -4));edge.add(new AlgoEdge(2, 3, -3));edge.add(new AlgoEdge(2, 4, 9));edge.add(new AlgoEdge(3, 1, -2));edge.add(new AlgoEdge(4, 0, 2));edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}/*** @Description: 返回一个图,为算法导论图24-4改变版,有负权回路有向环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap2() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, -4));edge.add(new AlgoEdge(2, 3, -3));edge.add(new AlgoEdge(2, 4, 9));edge.add(new AlgoEdge(3, 1, -2));edge.add(new AlgoEdge(4, 0, 2));edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}/*** @Description: 返回一个图,为算法导论图24-4改变版,有向无环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap3() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, -4));edge.add(new AlgoEdge(2, 3, -3));edge.add(new AlgoEdge(2, 4, 9));//edge.add(new AlgoEdge(3, 1, -2));//edge.add(new AlgoEdge(4, 0, 2));//edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}/*** @Description: 返回一个图,为算法导论图24-4改变版,无负权有向环图* @Author: The_Sam* @Datetime: 2017/5/8 21:22* @Params: []* @Return: AlgoGraph*/static public AlgoGraph defaultMap4() {ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>();edge.add(new AlgoEdge(0, 1, 6));edge.add(new AlgoEdge(0, 2, 7));edge.add(new AlgoEdge(1, 2, 8));edge.add(new AlgoEdge(1, 3, 5));edge.add(new AlgoEdge(1, 4, 4));edge.add(new AlgoEdge(2, 3, 3));edge.add(new AlgoEdge(2, 4, 9));//edge.add(new AlgoEdge(3, 1, -2));//edge.add(new AlgoEdge(4, 0, 2));//edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7));int original = 0;int nodenum = 5;return new AlgoGraph(original, nodenum, edge);}
}

AlgoEdge.java表示边的代码附上
package util;/*** Created by The_Sam on 2017/5/8.*/
public class AlgoEdge {public int u,v;public int cost;public AlgoEdge(int u, int v, int cost) {this.u = u;this.v = v;this.cost = cost;}
}




这篇关于算法导论——24.3 Dijkstra最短路径算法java实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/860512

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu