forked from kodecocodes/swift-algorithm-club
-
Notifications
You must be signed in to change notification settings - Fork 0
/
EncodeAndDecodeTree.swift
95 lines (74 loc) · 1.96 KB
/
EncodeAndDecodeTree.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//
// EncodeAndDecodeTree.swift
//
//
// Created by Kai Chen on 19/07/2017.
//
//
import Foundation
protocol BinaryNodeEncoder {
func encode<T>(_ node: BinaryNode<T>?) throws -> String
}
protocol BinaryNodeDecoder {
func decode<T>(from string: String) -> BinaryNode<T>?
}
public class BinaryNodeCoder<T: Comparable>: BinaryNodeEncoder, BinaryNodeDecoder {
// MARK: Private
private let separator: Character = ","
private let nilNode = "X"
private func decode<T>(from array: inout [String]) -> BinaryNode<T>? {
guard !array.isEmpty else {
return nil
}
let value = array.removeLast()
guard value != nilNode, let val = value as? T else {
return nil
}
let node = BinaryNode<T>(val)
node.left = decode(from: &array)
node.right = decode(from: &array)
return node
}
// MARK: Public
public init() {}
public func encode<T>(_ node: BinaryNode<T>?) throws -> String {
var str = ""
node?.preOrderTraversal { data in
if let data = data {
let string = String(describing: data)
str.append(string)
} else {
str.append(nilNode)
}
str.append(separator)
}
return str
}
public func decode<T>(from string: String) -> BinaryNode<T>? {
var components = string.split(separator: separator).reversed().map(String.init)
return decode(from: &components)
}
}
public class BinaryNode<Element: Comparable> {
public var val: Element
public var left: BinaryNode?
public var right: BinaryNode?
public init(_ val: Element, left: BinaryNode? = nil, right: BinaryNode? = nil) {
self.val = val
self.left = left
self.right = right
}
public func preOrderTraversal(visit: (Element?) throws -> ()) rethrows {
try visit(val)
if let left = left {
try left.preOrderTraversal(visit: visit)
} else {
try visit(nil)
}
if let right = right {
try right.preOrderTraversal(visit: visit)
} else {
try visit(nil)
}
}
}