最短路径算法(旅游规划实例java语言)

Dijkstra算法

简介

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点(不是所有节点到所有节点)的最短路径。 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止

算法思想

通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。

此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。(u中间的距离如何计算,是通过s集合中的顶点作为中转点计算得出,s最开始只有一个起始点,但不断地从u中取出min距离的顶点到s,再根据这个顶点作为中转点更新u中的距离)

初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是”起点s到该顶点的路径”。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 … 重复该操作,直到遍历完所有顶点。

————————————————

参考链接:https://blog.csdn.net/xushiyu1996818/article/details/90516598

/**用dijkstra算法求出first节点到其他节点的最短距离<br>

* 声明两个set,open和close,open用于存储未遍历的节点,close用来存储已遍历的节点<br>

* 声明两个map,一个map为distance,key为vertex,value为double,是计算现在得到的这个vertex距离起始点的最短路径<br>

* 一个map为path,key为vertex,value为vertex,是出发点到结束点的最短距离的路径的最后的中转节点<br>

* 初始阶段,将所有节点放入open<br>

* distance里面先初始为doubleMax,Path先初始为vertex自己<br>

* 将起始点放入close,设置distance=0,path=自己,更新起始点周围的节点的距离,设置他们的distance=边的距离,path=起始点<br>

* 以初始节点为中心向外一层层遍历,获取离指定节点最近的子节点(遍历open中的vertex,找到distance最小的vertex)<br>

* 放入close并从新计算路径,直至close包含所有子节点(或者说open为空)<br>

* @param first

* @return 返回一个map为distance,key为vertex,value为double,是计算现在得到的这个vertex距离起始点的最短路径<br>

*/

public HashMap<Vertex<T>, Double> getSmallestDistanceDijkstra(String first){

Set<Vertex<T>> open=new HashSet<>();

Set<Vertex<T>> close=new HashSet<>();

HashMap<Vertex<T>, Vertex<T>> path=new HashMap<>();

HashMap<Vertex<T>, Double> distance=new HashMap<>();

Set<Vertex<T>> set=getVertexSet();

Vertex<T> firstVertex=vertexMap.get(first);

Edge edge;

if(firstVertex==null){

return distance;

}

//初始阶段,将所有节点放入open,distance里面先初始为doubleMax,Path先初始为vertex自己

for(Vertex<T> vertex:set){

open.add(vertex);

distance.put(vertex, Double.MAX_VALUE);

path.put(vertex, vertex);

}

//将起始点放入close,设置distance=0,path=自己,更新起始点周围的节点的距离,设置他们的distance=边的距离,path=起始点

open.remove(firstVertex);

close.add(firstVertex);

distance.put(firstVertex, 0.0);

path.put(firstVertex, firstVertex);

Iterator<Edge> edgeIterator=firstVertex.getEdgeIterator();

while(edgeIterator.hasNext()){

edge=edgeIterator.next();

Vertex<T> endVertex=edge.getEndVertex();

distance.put(endVertex, edge.getWeight());

path.put(endVertex, firstVertex);

}

//以初始节点为中心向外一层层遍历,获取离指定节点最近的子节点(遍历open中的vertex,找到distance最小的vertex)

//放入close并从新计算路径,直至close包含所有子节点(或者说open为空)

while(!open.isEmpty()){

Double minDistance=Double.MAX_VALUE;

Vertex<T> minVertex=null;

for(Vertex<T> vertex:open){

if(minDistance>distance.get(vertex)){

//遍历open中的vertex,找到distance最小的vertex

minDistance=distance.get(vertex);

minVertex=vertex;

}

}

////放入close并从新计算路径,直至close包含所有子节点(或者说open为空)

open.remove(minVertex);

close.add(minVertex);

//System.out.println("加入节点:"+minVertex.getLabel());

edgeIterator=minVertex.getEdgeIterator();

while(edgeIterator.hasNext()){

edge=edgeIterator.next();

Vertex<T> endVertex=edge.getEndVertex();

Double weight=edge.getWeight();

//如果之前的距离>初始到minVertex+minVertex到endVertex,就替换

if(distance.get(endVertex)>distance.get(minVertex)+weight){

distance.put(endVertex, distance.get(minVertex)+weight);

path.put(endVertex, minVertex);

}

}

}

for(Vertex<T> vertex:set){

System.out.println("到顶点:"+vertex.getLabel()+

" ,最短距离为:"+distance.get(vertex)+" ,最后中转点为:"+path.get(vertex).getLabel());

}

return distance;

}

下面以欧洲旅游规划为例模拟欧洲铁路系统中两个城市之间最便宜的路线

public class Service {//服务类

String name;     int cost;      int distance;       Service next;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getCost() {

return cost;

}

public void setCost(int cost) {

this.cost = cost;

}

public int getDistance() {

return distance;

}

public void setDistance(int distance) {

this.distance = distance;

}

public Service(String name, int cost, int distance) {

super();

this.name = name;     this.cost = cost;    this.distance = distance;

next=null;

}

}

public class City {//代表图上的结点

Service first;    String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public City(String name) {

super();

this.name = name;

first=null;

}

public void addService(Service s) {

if(first==null) {

first=s;

}else {

Service w=first;

while(w.next!=null) {

w=w.next;

}w.next=s;}

}

public int getdistance(String name) {

Service w=first;

while(w!=null) {

if(w.getName().equals(name)) {

return w.distance;

}

w=w.next;

}

return 0;

}     }

public class RailSystem {//模拟铁路系统

SeqList<City> citylist;

HashMap<City, City>path;           HashMap<City,Integer>distance;

String  from_city;

City currentcity;

public RailSystem() {

citylist= new SeqList<City>(20);

}

public void addCity(String name) {

citylist.add(new City(name));

}

public City getCity(String name) {

for(int i=0;i<citylist.size();i++) {

if(citylist.get(i).getName().equals(name)) {

return citylist.get(i);

}

}return null;

}

public void calc_route(String first){//计算各结点最小价格

from_city=null;

Set<City> cityin=new HashSet<>();//未遍历的结点

Set<City> cityout=new HashSet<>();//已遍历的结点

path=new HashMap<>();//各结点的先驱结点

distance=new HashMap<>();//起始点到此结点的距离

Service edge;

for(int i=0;i<citylist.size();i++) {//把所有结点放入cityin

cityin.add(citylist.get(i));

distance.put(citylist.get(i), Integer.MAX_VALUE);

path.put(citylist.get(i),citylist.get(i));

}

City firstCity=getCity(first);//设置初始状态

currentcity=firstCity;

cityin.remove(firstCity);

cityout.add(firstCity);

distance.put(firstCity, 0);

path.put(firstCity, firstCity);

edge=firstCity.first;

while(edge !=null) {

City nextcity=getCity(edge.name);

distance.put(nextcity, edge.getCost());

path.put(nextcity, firstCity);

edge=edge.next;

}

while(!cityin.isEmpty()) {//下面开始由中心向外一层层遍历

int minDistance=Integer.MAX_VALUE;

City minCity=null;

for(City c:cityin) {//得到距离(价格)最近的城市

if(minDistance >distance.get(c)){

minDistance=distance.get(c);

minCity=c;

}

}

cityin.remove(minCity);

cityout.add(minCity);

/////////////////////下面要更新距离

if(minCity!=null) {

edge=minCity.first;}

while(edge !=null) {

City nextcity=getCity(edge.name);

int cost=edge.cost;

if(distance.get(nextcity)>distance.get(minCity)+cost) {

distance.put(nextcity, distance.get(minCity)+cost);

path.put(nextcity, minCity);

}

edge=edge.next;

}

}

}

public String recover_route(String name) {//根据目的地返回路线与价格

SeqList<City> route_=new SeqList<City>(20);

String _route="The cheapest route from "+currentcity.name+" to "+name+"\n";

int length=0;

City endCity=getCity(name);

int cost=distance.get(endCity);

City city=endCity;

while(endCity !=currentcity) {

endCity=path.get(city);

length=length+city.getdistance(endCity.name);

route_.add(city);

city=endCity;

}route_.add(city);

_route=_route+"costs "+String.valueOf(cost)+" euros and spans "+String.valueOf(length)+" kilometers"+"\n";

for(int i=route_.size()-1;i>=0;i--) {

_route=_route+route_.get(i).name;

if(route_.get(i-1)!=null) {

_route=_route+" to ";

}

}

return from_city=_route;

}

public void reset() {//系统重置

path=new HashMap<>();

distance=new HashMap<>();

}

public void loadService(String filename) throws IOException {//装载结点数据

File file=new File(filename);

    FileReader fr=new FileReader(file);

    BufferedReader br=new BufferedReader(fr);

  String data=null;

  while((data=br.readLine())!=null) {

  String[]datas=data.split(" ");

  if(getCity(datas[0])==null) {

  addCity(datas[0]);

  getCity(datas[0]).addService(new Service(datas[1],Integer.parseInt(datas[2]),Integer.parseInt(datas[3])));

  }else {

  getCity(datas[0]).addService(new Service(datas[1],Integer.parseInt(datas[2]),Integer.parseInt(datas[3])));

  }

  }

}

public void run() throws IOException {//运行

loadService("F:\\java\\workspace\\Exprience4\\services.txt");

String start=" ";

String end=" ";

while(!start.equals("quit") &&!end.equals("quit")) {

System.out.println("Enter a start and destination city: <'quit' to exit>");

Scanner in=new Scanner(System.in);

    start=in.next();

    end=in.next();

    if(!(getCity(start)==null)&& !(getCity(end)==null)) {

    calc_route(start);

    System.out.println(recover_route(end));}

}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342