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. 题目描述 如题,给出一个有向图,请输出从某一点出 ...
随机推荐
- Windows下memcached的安装配置
下载windows 32位或64位 memcached 下载 memcached_dll 1.将第一个包解压放某个盘下面,比如在c:\memcached.2.在终端(也即cmd命令界面)下输入 'c: ...
- Python中map()函数浅析
MapReduce的设计灵感来自于函数式编程,这里不打算提MapReduce,就拿python中的map()函数来学习一下. 文档中的介绍在这里: map(function, iterable, .. ...
- ubuntu中使用usb-creator制作live usb
1.实验环境 ubuntu14.04 2.启动usb-creator 2.1 单击桌面左上角的搜索图标,输入usb-creator,然后选择“应用程序"中的”启动盘创建器“ 2.2 终端中输 ...
- Asp.Net MVC4 系列--进阶篇之路由 (2)
上一篇介绍了Asp.Net MVC 中,从Http Pipeline上接收到请求如何匹配,匹配限制,以及如何控制在指定命名空间查找,解析出controller和action,并传参. 这篇主要介绍如何 ...
- 部署LAMP+NFS实现双Web服务器负载均衡
一.需求分析 1.前端需支持更大的访问量,单台Web服务器已无法满足需求了,则需扩容Web服务器: 2.虽然动态内容可交由后端的PHP服务器执行,但静态页面还需要Web服务器自己解析,那是否意味着多台 ...
- DevOps之网络
唠叨话 关于德语噢屁事的知识点,仅提供专业性的精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <网络(Network)> 关于网络的网络架构和网络模型:知识与技能的层次(知道. ...
- (@WhiteTaken)设计模式学习——代理模式
今天学习了一下代理模式,代理模式分为很多种.目前感觉有两种是需要学习一下的. 静态代理模式 动态代理模式 1. 静态代理模式 需要被代理的类,实现一个或者多个接口. 代理类需要实现被代理类的接口,在此 ...
- C#同步方法转异步
public async Task DelayAsync() { await Task.Run(()=>Delay()); } private void Delay() { } 本作品采用知识共 ...
- [译]ASP.NET Core 2.0 依赖注入
问题 如何使用 ASP.NET Core 服务容器进行依赖注入? 答案 创建一个服务 public interface IGreetingService { string Greet(string t ...
- 购物篮算法的理解-基于R的应用
是无监督机器学习方法,用于知识发现,而非预测,无需事先对训练数据进行打标签,因为无监督学习没有训练这个步骤.缺点是很难对关联规则学习器进行模型评估,一般都可以通过肉眼观测结果是否合理. 一,概念术语 ...