Dijkstra算法(Swift版)
原理
我们知道,使用Breadth-first search算法能够找到到达某个目标的最短路径,但这个算法没考虑weight
,因此我们再为每个edge添加了权重后,我们就需要使用Dijkstra算法来寻找权重和最小的路径。
其实原理很简单,我们最终的目的是计算出每一个节点到起点的权重之和,同时获取得到这个权重和的路径数组。
那么权重和最小的那个自然就是我们要的结果。
在该算法中有一下几个核心的思想:
- 当我们遍历到某个节点时,计算出该节点到起点的权重和之后=,该节点就不在使用了,或删除或者标记为已检阅
- 当该节点的某个neighbor节点加上权重的值小于该neighbor节点时,跟新该neighbor节点的数据
实现这个算法的方式有多种,在该文章中,我们把某些数据直接封装到了节点中。
Vertex
Vertex.swift
import Foundation
open class Vertex {
open var identifier: String
open var neighbors: [(Vertex, Double)] = []
open var pathLengthFromStart = Double.infinity
open var pathVerticesFromStart: [Vertex] = []
public init(identifier: String) {
self.identifier = identifier
}
open func clearCache() {
pathLengthFromStart = Double.infinity
pathVerticesFromStart = []
}
}
extension Vertex: Hashable {
open var hashValue: Int {
return identifier.hashValue
}
}
extension Vertex: Equatable {
public static func ==(lhs: Vertex, rhs: Vertex) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
Dijkstra
Dijkstra.swift
import Foundation
public class Dijkstra {
private var totalVertices: Set<Vertex>
public init(vertices: Set<Vertex>) {
totalVertices = vertices
}
private func clearCache() {
totalVertices.forEach { $0.clearCache() }
}
public func findShortestPaths(from startVertex: Vertex) {
clearCache()
var currentVertices = self.totalVertices
startVertex.pathLengthFromStart = 0
startVertex.pathVerticesFromStart.append(startVertex)
var currentVertex: Vertex? = startVertex
while let vertex = currentVertex {
currentVertices.remove(vertex)
let filteredNeighbors = vertex.neighbors.filter { currentVertices.contains($0.0) }
for neighbor in filteredNeighbors {
let neighborVertex = neighbor.0
let weight = neighbor.1
let theoreticNewWeight = vertex.pathLengthFromStart + weight
if theoreticNewWeight < neighborVertex.pathLengthFromStart {
neighborVertex.pathLengthFromStart = theoreticNewWeight
neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart
neighborVertex.pathVerticesFromStart.append(neighborVertex)
}
}
if currentVertices.isEmpty {
currentVertex = nil
break
}
currentVertex = currentVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart }
}
}
}
演示
我们就演示这个例子
//: Playground - noun: a place where people can play
import Foundation
// last checked with Xcode 9.0b4
#if swift(>=4.0)
print("Hello, Swift 4!")
#endif
var vertices: Set<Vertex> = Set()
/// Create vertexs
var vertexA = Vertex(identifier: "A")
var vertexB = Vertex(identifier: "B")
var vertexC = Vertex(identifier: "C")
var vertexD = Vertex(identifier: "D")
var vertexE = Vertex(identifier: "E")
var vertexF = Vertex(identifier: "F")
/// Setting neighbors
vertexA.neighbors.append(contentsOf: [(vertexB, 5), (vertexD, 2)])
vertexB.neighbors.append(contentsOf: [(vertexC, 4), (vertexE, 2)])
vertexC.neighbors.append(contentsOf: [(vertexE, 6), (vertexF, 3)])
vertexD.neighbors.append(contentsOf: [(vertexB, 8), (vertexE, 7)])
vertexE.neighbors.append(contentsOf: [(vertexF, 1)])
vertices.insert(vertexA)
vertices.insert(vertexB)
vertices.insert(vertexC)
vertices.insert(vertexD)
vertices.insert(vertexE)
vertices.insert(vertexF)
let dijkstra = Dijkstra(vertices: vertices)
dijkstra.findShortestPaths(from: vertexA)
for vertex in vertices {
let paths = vertex.pathVerticesFromStart.map({ $0.identifier })
print("(A=>" + vertex.identifier + "): " + paths.joined(separator: " -> "))
}
打印结果:
(A=>B): A -> B
(A=>A): A
(A=>F): A -> B -> E -> F
(A=>C): A -> B -> C
(A=>D): A -> D
(A=>E): A -> B -> E
主要代码来自于Dijkstra
Dijkstra算法(Swift版)的更多相关文章
- 朴素版和堆优化版dijkstra和朴素版prim算法比较
1.dijkstra 时间复杂度:O(n^2) n次迭代,每次找到距离集合S最短的点 每次迭代要用找到的点t来更新其他点到S的最短距离. #include<iostream> #inclu ...
- Java用Dijkstra算法实现地图两点的最短路径查询(Android版)
地图上实现最短路径的查询,据我了解的,一般用Dijkstra算法和A*算法来实现.由于这是一个课程项目,时间比较急,而且自己不熟悉A*算法,所以参考网上的Dijkstra算法(http://blog. ...
- 快速排序OC、Swift版源码
前言: 你要问我学学算法在工作当中有什么用,说实话,当达不到那个地步的时候,可能我们不能直接的感觉到它的用处!你就抱着这样一个心态,当一些APP中涉及到算法的时候我不想给其他人画界面!公司的项目也是暂 ...
- 单源最短路径问题之dijkstra算法
欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 算法的原理 以源点开始,以源点相连的顶点作为向外延伸的顶点,在所有这些向外延伸的顶 ...
- 经典算法研究系列:二、Dijkstra 算法初探
July 二零一一年一月 本文主要参考:算法导论 第二版.维基百科. 一.Dijkstra 算法的介绍 Dijkstra 算法,又叫迪科斯彻算法(Dijkstra),算法解决的是有向图中单个源点到 ...
- 配对堆优化Dijkstra算法小记
关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏 ...
- 最短路径-Dijkstra算法与Floyd算法
一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1 ADE:2 ADCE:3 ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径 ...
- 非负权值有向图上的单源最短路径算法之Dijkstra算法
问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度.求解该问题的算法一般为Dijkstra算法. 假设图顶点个数为n,则针对 ...
- luogu P3371 & P4779 单源最短路径spfa & 最大堆优化Dijkstra算法
P3371 [模板]单源最短路径(弱化版) 题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779. 题目描述 如题,给出一个有向图,请输出从某一点出 ...
随机推荐
- C++格式化硬盘程序
#include using namespace std; //声明命名空间 void main() { char format[12]="format", name[10], ...
- HDU1251统计难题(水字典树)
统计难题 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others) Total Subm ...
- 一步一个坑 - WinDbg调试.NET程序
引言 第一次用WinDbg来排查问题,花了很多时间踩坑,记录一下希望对后面的同学有些帮助. 客户现场软件出现偶发性的界面卡死现象一直找不出原因,就想着让客户用任务管理器生成了一个dump文件发给我,我 ...
- 简单的CSS颜色查看工具
可以通过输入ARGB(A代表透明度)格式或者HEX格式查看颜色,也可以进行ARGB格式和者HEX格式转换,如下图 使用C#编写,我已将源代码压缩上传 下载地址:http://files.cnblogs ...
- 1.ElasticSearch介绍及基本概念
一.ElasticSearch介绍 一个采用RESTful API标准的高扩展性的和高可用性的实时性分析的全文搜索工具 基于Lucene[开源的搜索引擎框架]构建 ElasticSearch是一个面向 ...
- break和continue 的区别
区别 break和continue都可在循环语句里面使用,也都可以控制外层的循环.但是continue只能在循环语句里面使用,break也可以使用在switch语句里面. break具体作用在循环语句 ...
- javaScript基础的基础
JavaScript是一个脚本语言,需要有宿主文件,他的宿主文件是HTML文件. 与JAVA没有直接关系 一般写在 1.head里面 2.body里面 3.</html>后面 一般写在&l ...
- jemalloc 快速上手攻略
引言 - 赠送个 Cygwin (加精) Cygwin 有它存在的合理性. 至少比 wine 好太多了. 它主要功能是在winds上面简易的模拟出linux环境, 比虚拟机 轻量一点点. 坑也不少, ...
- 阻塞IO
服务端 from socket import * server = socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8080)) server ...
- python中sys.exit()和os._exit(0)退出程序
python中退出程序的两种方法,0为默认状态,可以为空,两者均会退出当前运行的程序,os._exit(0)中的0不能省略 sys.exit(0):可以捕获SystemExit异常,然后做相应的清理工 ...