Swift数据结构之Dijkstra

代码实现

(包括图,边,点)

public class DijkstraEdge<T:Equatable & Hashable>:Equatable {
    public var from:DijkstraNode<T>
    public var to:DijkstraNode<T>
    public var weight:Double

    public init(weight:Double, from:DijkstraNode<T>, to:DijkstraNode<T>) {
        self.weight = weight
        self.from = from
        self.to = to
        from.edges.append(self)
    }
}

    
public func == <T: Equatable> (lhs: DijkstraEdge<T>, rhs: DijkstraEdge<T>) ->
Bool {
    guard lhs.from.value == rhs.from.value else {
        return false
    }
    guard lhs.to.value == rhs.to.value else {
        return false
    }
    return true
}

    
extension DijkstraEdge: Hashable {
    public var hashValue: Int {
        get {
            let stringHash = "\(from.value)->\(to.value)"
            return stringHash.hashValue
        }
    }
}

public class DijkstraNode<T:Equatable & Hashable>:Equatable {

    public var value:T
    public var edges:[DijkstraEdge<T>]
    public var visited:Bool

    public var distance:Int = Int.max

    public var previous:DijkstraNode<T>?

    public init(value:T, edges:[DijkstraEdge<T>], visited:Bool) {
        self.value = value
        self.edges = edges
        self.visited = visited
    }
}

    
public func == <T: Equatable> (lhs: DijkstraNode<T>, rhs: DijkstraNode<T>) -> Bool {
    guard lhs.value == rhs.value else {
        return false
    }
    
    return true
}

    
extension DijkstraNode: Hashable {
    public var hashValue: Int {
        get {
            return value.hashValue
        }
    }
}


public class DijkstraGraph<T:Hashable & Equatable> {
    public var nodes:[DijkstraNode<T>]
 
    public init(nodes:[DijkstraNode<T>]) {
        self.nodes = nodes
    }
    
    public static func dijkstraPath(startNode:DijkstraNode<T>,
    graph:DijkstraGraph<T>, finishNode:DijkstraNode<T>) {
        var unvisitedNodes = Set<DijkstraNode<T>>(graph.nodes)
    
        startNode.distance = 0

        var currentNode:DijkstraNode<T> = startNode

        while (finishNode.visited == false) {
            for edge in currentNode.edges.filter({ (edge) -> Bool in
                return edge.to.visited == false
            }) {
            let temporaryDistance = currentNode.distance +
            Int(edge.weight)

                if edge.to.distance > temporaryDistance {
                    edge.to.distance = temporaryDistance
                    edge.to.previous = currentNode
                }
            }

            currentNode.visited = true
 
            unvisitedNodes.remove(currentNode)

            if let newCurrent = unvisitedNodes.sorted(by: {
            (nodeA, nodeB) -> Bool in
                nodeA.distance  < nodeB.distance
            }).first {
                currentNode = newCurrent
            } else {
                break
            }
        }

        DijkstraGraph.printShortestPath(node: finishNode)
            }

        public static func printShortestPath(node:DijkstraNode<T>) {
            if let previous = node.previous {
                DijkstraGraph.printShortestPath(node: previous)
            } else {
                print("Shortest path:")
            }
                print("->\(node.value)", terminator:"")
        }
}

实例

设现存一图如下:
在这里插入图片描述
先创建节点信息,接着边,最后图

let nodeA = DijkstraNode(value: "A", edges: [], visited: false)
let nodeB = DijkstraNode(value: "B", edges: [], visited: false)
let nodeC = DijkstraNode(value: "C", edges: [], visited: false)
let nodeD = DijkstraNode(value: "D", edges: [], visited: false)
let nodeE = DijkstraNode(value: "E", edges: [], visited: false)
    
let edgeAB = DijkstraEdge(weight: 3, from: nodeA, to: nodeB)
let edgeBA = DijkstraEdge(weight: 3, from: nodeB, to: nodeA)
let edgeAC = DijkstraEdge(weight: 1, from: nodeA, to: nodeC)
let edgeCA = DijkstraEdge(weight: 1, from: nodeC, to: nodeA)
let edgeBC = DijkstraEdge(weight: 1, from: nodeB, to: nodeC)
let edgeCB = DijkstraEdge(weight: 1, from: nodeC, to: nodeB)
let edgeBD = DijkstraEdge(weight: 2, from: nodeB, to: nodeD)
let edgeDB = DijkstraEdge(weight: 2, from: nodeD, to: nodeB)
let edgeDE = DijkstraEdge(weight: 1, from: nodeD, to: nodeE)
let edgeED = DijkstraEdge(weight: 1, from: nodeE, to: nodeD)
let edgeCE = DijkstraEdge(weight: 8, from: nodeC, to: nodeE)
let edgeEC = DijkstraEdge(weight: 8, from: nodeE, to: nodeC)
    

let graph = DijkstraGraph(nodes: [nodeA,nodeB,nodeC,nodeD,nodeE])

结果

Shortest path:
->A->C->B->D->E
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值