原理

我们知道,使用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版)的更多相关文章

  1. 朴素版和堆优化版dijkstra和朴素版prim算法比较

    1.dijkstra 时间复杂度:O(n^2) n次迭代,每次找到距离集合S最短的点 每次迭代要用找到的点t来更新其他点到S的最短距离. #include<iostream> #inclu ...

  2. Java用Dijkstra算法实现地图两点的最短路径查询(Android版)

    地图上实现最短路径的查询,据我了解的,一般用Dijkstra算法和A*算法来实现.由于这是一个课程项目,时间比较急,而且自己不熟悉A*算法,所以参考网上的Dijkstra算法(http://blog. ...

  3. 快速排序OC、Swift版源码

    前言: 你要问我学学算法在工作当中有什么用,说实话,当达不到那个地步的时候,可能我们不能直接的感觉到它的用处!你就抱着这样一个心态,当一些APP中涉及到算法的时候我不想给其他人画界面!公司的项目也是暂 ...

  4. 单源最短路径问题之dijkstra算法

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 算法的原理 以源点开始,以源点相连的顶点作为向外延伸的顶点,在所有这些向外延伸的顶 ...

  5. 经典算法研究系列:二、Dijkstra 算法初探

    July   二零一一年一月 本文主要参考:算法导论 第二版.维基百科. 一.Dijkstra 算法的介绍 Dijkstra 算法,又叫迪科斯彻算法(Dijkstra),算法解决的是有向图中单个源点到 ...

  6. 配对堆优化Dijkstra算法小记

    关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏 ...

  7. 最短路径-Dijkstra算法与Floyd算法

    一.最短路径 ①在非网图中,最短路径是指两顶点之间经历的边数最少的路径. AE:1    ADE:2   ADCE:3   ABCE:3 ②在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径 ...

  8. 非负权值有向图上的单源最短路径算法之Dijkstra算法

    问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度.求解该问题的算法一般为Dijkstra算法. 假设图顶点个数为n,则针对 ...

  9. luogu P3371 & P4779 单源最短路径spfa & 最大堆优化Dijkstra算法

    P3371 [模板]单源最短路径(弱化版) 题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779. 题目描述 如题,给出一个有向图,请输出从某一点出 ...

随机推荐

  1. ASP.NET没有魔法——第一个ASP.NET应用《MyBlog》

    创建一个ASP.NET MVC应用程序 在之前文章中介绍了ASP.NET中提供了3个开发动态网页的框架,分别是Web Form.MVC以及Web Pages,也大概介绍了它们的特点. 其中MVC对于其 ...

  2. 自动化selenium开发

    一.开发环境搭建 1.Firefox浏览器 1.1 下载firefix并安装. 1.2 Firefox中打开"开始菜单“ -> ”开发者“ -> ”获取更多工具“ -> 搜 ...

  3. this到底指向哪里

    this指向调用它的对象 首先要明确,this指向调用方,谁调用,this指向谁. 直接调用 举个栗子: var test = 'window' ; function testThis () { va ...

  4. UWP 手绘视频创作工具技术分享系列 - 位图的绘制

    前面我们针对 SVG 的解析和绘制做了介绍,SVG 是图片的一种形式,而另一种很重要的图片是:位图,包括 png.jpeg.bmp 等格式.位图的基本规则是,组成的基本元素是像素点,由宽度 * 高度个 ...

  5. Session详解及集群共享

    Session的介绍 维基百科:会话(session)是一种持久网络协议,在用户(或用户代理)端和服务器端之间创建关联,从而起到交换数据包的作用机制,session在网络协议(例如telnet或FTP ...

  6. Android Parcelable理解与使用(对象序列化)

    http://my.oschina.net/zhoulc/blog/172163 parcel定义介绍: android提供了一种新的类型:parcel(英文解释:包裹,小包),本类用来封装数据的容器 ...

  7. 张高兴的 Xamarin.Android 学习笔记:(一)环境配置

    最近在自学 Xamarin 和 Android ,同时发现国内在做 Xamarin 的不多.我在自学中间遇到了很多问题,而且百度到的很多教程也有些过时,现在打算写点东西稍微总结下,顺便帮后人指指路了. ...

  8. JavaScript命令模式

    第一,命令模式: (1)用于消除调用者和接收者之间直接的耦合的模式,并且可以对(调用这个过程进行留痕操作) (2)真的不要乱用这个模式,以为他使你简单调用写法变得非常的复杂和有些难以理解. (3)你的 ...

  9. 【转】Gvim配置(Windows and Linux)for C++|gvim编译运行c/c++程序

    转载地址:http://blog.csdn.net/onepiecehuiyu/article/details/8934366 http://mawenhao19930620.blog.163.com ...

  10. spring-data-jpa 中,如果使用了one-to-many , many-to-one的注释,会在Jackson进行json字符串化的时候出现错误

    问题: spring-data-jpa 中,如果使用了one-to-many , many-to-one的注释,会在Jackson 2.7.0 进行json字符串化的时候出现错误. 解决办法: 通过在 ...