Skip to content

Commit 9a363c7

Browse files
committed
Minimum Spanning Tree (Kruskal's and Prim's)
1 parent d7d8326 commit 9a363c7

File tree

14 files changed

+703
-0
lines changed

14 files changed

+703
-0
lines changed
21.6 KB
Loading

Minimum Spanning Tree/Images/prim.png

18.6 KB
Loading

Minimum Spanning Tree/Kruskal.swift

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// Kruskal.swift
3+
//
4+
//
5+
// Created by xiang xin on 16/3/17.
6+
//
7+
//
8+
9+
10+
func minimumSpanningTreeKruskal<T>(graph: Graph<T>) -> (cost: Int, tree: Graph<T>) {
11+
var cost: Int = 0
12+
var tree = Graph<T>()
13+
let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight })
14+
15+
var unionFind = UnionFind<T>()
16+
for vertex in graph.vertices {
17+
unionFind.addSetWith(vertex)
18+
}
19+
20+
for edge in sortedEdgeListByWeight {
21+
let v1 = edge.vertex1
22+
let v2 = edge.vertex2
23+
if !unionFind.inSameSet(v1, and: v2) {
24+
cost += edge.weight
25+
tree.addEdge(edge)
26+
unionFind.unionSetsContaining(v1, and: v2)
27+
}
28+
}
29+
30+
return (cost: cost, tree: tree)
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
The following code demonstrates getting MST of the graph below by both
3+
Kruskal's and Prim's algorithms.
4+
*/
5+
6+
func minimumSpanningTreeKruskal<T>(graph: Graph<T>) -> (cost: Int, tree: Graph<T>) {
7+
var cost: Int = 0
8+
var tree = Graph<T>()
9+
let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight })
10+
11+
var unionFind = UnionFind<T>()
12+
for vertex in graph.vertices {
13+
unionFind.addSetWith(vertex)
14+
}
15+
16+
for edge in sortedEdgeListByWeight {
17+
let v1 = edge.vertex1
18+
let v2 = edge.vertex2
19+
if !unionFind.inSameSet(v1, and: v2) {
20+
cost += edge.weight
21+
tree.addEdge(edge)
22+
unionFind.unionSetsContaining(v1, and: v2)
23+
}
24+
}
25+
26+
return (cost: cost, tree: tree)
27+
}
28+
29+
func minimumSpanningTreePrim<T>(graph: Graph<T>) -> (cost: Int, tree: Graph<T>) {
30+
var cost: Int = 0
31+
var tree = Graph<T>()
32+
33+
if graph.vertices.isEmpty {
34+
return (cost: cost, tree: tree)
35+
}
36+
37+
var visited = Set<T>()
38+
var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>(
39+
sort: { $0.weight < $1.weight })
40+
41+
priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil))
42+
while let head = priorityQueue.dequeue() {
43+
let vertex = head.vertex
44+
if visited.contains(vertex) {
45+
continue
46+
}
47+
visited.insert(vertex)
48+
49+
cost += head.weight
50+
if let prev = head.parent {
51+
tree.addEdge(vertex1: prev, vertex2: vertex, weight: head.weight)
52+
}
53+
54+
if let neighbours = graph.adjList[vertex] {
55+
for neighbour in neighbours {
56+
let nextVertex = neighbour.vertex
57+
if !visited.contains(nextVertex) {
58+
priorityQueue.enqueue((vertex: nextVertex, weight: neighbour.weight, parent: vertex))
59+
}
60+
}
61+
}
62+
}
63+
64+
return (cost: cost, tree: tree)
65+
}
66+
67+
/*:
68+
![Graph](mst.png)
69+
*/
70+
71+
var graph = Graph<Int>()
72+
graph.addEdge(vertex1: 1, vertex2: 2, weight: 6)
73+
graph.addEdge(vertex1: 1, vertex2: 3, weight: 1)
74+
graph.addEdge(vertex1: 1, vertex2: 4, weight: 5)
75+
graph.addEdge(vertex1: 2, vertex2: 3, weight: 5)
76+
graph.addEdge(vertex1: 2, vertex2: 5, weight: 3)
77+
graph.addEdge(vertex1: 3, vertex2: 4, weight: 5)
78+
graph.addEdge(vertex1: 3, vertex2: 5, weight: 6)
79+
graph.addEdge(vertex1: 3, vertex2: 6, weight: 4)
80+
graph.addEdge(vertex1: 4, vertex2: 6, weight: 2)
81+
graph.addEdge(vertex1: 5, vertex2: 6, weight: 6)
82+
83+
print("===== Kruskal's =====")
84+
let result1 = minimumSpanningTreeKruskal(graph: graph)
85+
print("Minimum spanning tree total weight: \(result1.cost)")
86+
print("Minimum spanning tree:")
87+
print(result1.tree)
88+
89+
print("===== Prim's =====")
90+
let result2 = minimumSpanningTreePrim(graph: graph)
91+
print("Minimum spanning tree total weight: \(result2.cost)")
92+
print("Minimum spanning tree:")
93+
print(result2.tree)
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
// Undirected edge
3+
public struct Edge<T>: CustomStringConvertible {
4+
public let vertex1: T
5+
public let vertex2: T
6+
public let weight: Int
7+
8+
public var description: String {
9+
return "[\(vertex1)-\(vertex2), \(weight)]"
10+
}
11+
}
12+
13+
14+
// Undirected weighted graph
15+
public struct Graph<T: Hashable>: CustomStringConvertible {
16+
17+
public private(set) var edgeList: [Edge<T>]
18+
public private(set) var vertices: Set<T>
19+
public private(set) var adjList: [T: [(vertex: T, weight: Int)]]
20+
21+
public init() {
22+
edgeList = [Edge<T>]()
23+
vertices = Set<T>()
24+
adjList = [T: [(vertex: T, weight: Int)]]()
25+
}
26+
27+
public var description: String {
28+
var description = ""
29+
for edge in edgeList {
30+
description += edge.description + "\n"
31+
}
32+
return description
33+
}
34+
35+
public mutating func addEdge(vertex1 v1: T, vertex2 v2: T, weight w: Int) {
36+
edgeList.append(Edge(vertex1: v1, vertex2: v2, weight: w))
37+
vertices.insert(v1)
38+
vertices.insert(v2)
39+
if adjList[v1] == nil {
40+
adjList[v1] = [(vertex: v2, weight: w)]
41+
} else {
42+
adjList[v1]!.append((vertex: v2, weight: w))
43+
}
44+
45+
if adjList[v2] == nil {
46+
adjList[v2] = [(vertex: v1, weight: w)]
47+
} else {
48+
adjList[v2]!.append((vertex: v1, weight: w))
49+
}
50+
}
51+
52+
public mutating func addEdge(_ edge: Edge<T>) {
53+
addEdge(vertex1: edge.vertex1, vertex2: edge.vertex2, weight: edge.weight)
54+
}
55+
}

0 commit comments

Comments
 (0)