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. 题目描述 如题,给出一个有向图,请输出从某一点出 ...
随机推荐
- 【转】python time模块详解
python 的内嵌time模板翻译及说明 一.简介 time模块提供各种操作时间的函数 说明:一般有两种表示时间的方式: 第一种是时间戳的方式(相对于1970.1.1 00:00:0 ...
- jq 通过标签属性匹配标签
有时候会有这样的需求 在一堆的标签中定位到某个标签去获取值 这时候我们就可以通过使用自定义属性将这一堆标签打上不同的标记 通过属性定位标签了 下面是代码: <input class=" ...
- 移动端效果之CellSwiper
写在前面 接着之前的移动端效果讲解,刚好项目中需要使用到这一效果,去饿了么的组件库看了一下效果,发现效果和微信端的cellSwiper还是有点差别的,由于项目中又是使用的React,之前使用的Reac ...
- java通过shield链接Elasticsearch
本文mark了springboot中集成elasticsearch,并且实现连接带有shield权限管理的elasticsearch的方法. tips:首先建议java client版本和elasti ...
- c语言入门
c 语言现在是一门很流行的语言,它介于汇编语言和高级语言之间,我认为 它属于中级语言,如c语言 的指针 ,位操作符,等,因为接近于汇编语言,c语言的执行代码效率很高 现在大多数的系统 如unix,和l ...
- win10 3dmax 激活后反复激活和激活码无效问题
我也是遇到这个问题在网上找答案,像什么断网,清理注册表,删除某个.dat文件 各种试了好多都没管用 弄这个弄了五六个小时才总算成功 心累 现在我总结一下这些方法 我是第一条成功的 其他的我试着都没用 ...
- YYHS-string(线段树)
题解 这道题给你两个操作,一个升序,一个降序 我们可以观察到这个字符串都是由小写字母组成的,只有26个字符,所以我们开一个26个字符的线段树 每次查询的时候找到这个区间内'a'到'z'的数量,再判断一 ...
- Xuan.UWP.Framework
开篇博客,以前总是懒,不喜欢写博客什么,其实都是给自己找理由,从今天开始有空就写写博客.新手博客,写得不好轻喷,哈哈! 开始正题,微软移动平台,从WP7开始,经历了WP8,然后WP8.1,到目前得Wi ...
- Java基础-Random类(05)
随机数(Random) 作用:用于产生一个随机数 使用步骤(和Scanner类似) 导包import java.util.Random; 创建对象Random r = new Random(); 获取 ...
- LaunchScreen.storyboard 换图的问题
之前设置了`LaunchScreen.storyboard`,在这个storyboard中加了一个imageView,里面设置了一张图片launch.png,今天需要更换这个启动图片,我就直接去工程里 ...