Skip to content

Commit adf6065

Browse files
committed
Encode and Decode A Binary Tree
Encode and Decode A Binary Tree
1 parent 7cb6cf6 commit adf6065

File tree

6 files changed

+298
-0
lines changed

6 files changed

+298
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//: Playground - noun: a place where people can play
2+
3+
4+
func printTree(_ root: TreeNode?) {
5+
guard let root = root else {
6+
return
7+
}
8+
9+
var pointer = root
10+
11+
let leftVal = root.left == nil ? "nil" : root.left!.val
12+
let rightVal = root.right == nil ? "nil" : root.right!.val
13+
14+
print("val: \(root.val) left: \(leftVal) right: \(rightVal)")
15+
16+
printTree(root.left)
17+
printTree(root.right)
18+
}
19+
20+
let s = EncodeAndDecodeTree()
21+
22+
let node1 = TreeNode("a")
23+
let node2 = TreeNode("b")
24+
let node3 = TreeNode("c")
25+
let node4 = TreeNode("d")
26+
let node5 = TreeNode("e")
27+
28+
node1.left = node2
29+
node1.right = node3
30+
node3.left = node4
31+
node3.right = node5
32+
33+
let encodeStr = s.encode(node1)
34+
print(encodeStr)
35+
// "a b # # c d # # e # #"
36+
37+
38+
let root = s.decode(encodeStr)
39+
print("Tree:")
40+
printTree(root)
41+
/*
42+
Tree:
43+
val: a left: b right: c
44+
val: b left: nil right: nil
45+
val: c left: d right: e
46+
val: d left: nil right: nil
47+
val: e left: nil right: nil
48+
*/
49+
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//
2+
// EncodeAndDecodeTree.swift
3+
//
4+
//
5+
// Created by Kai Chen on 19/07/2017.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
public class TreeNode {
12+
public var val: String
13+
public var left: TreeNode?
14+
public var right: TreeNode?
15+
16+
public init(_ val: String, left: TreeNode? = nil, right: TreeNode? = nil) {
17+
self.val = val
18+
self.left = left
19+
self.right = right
20+
}
21+
}
22+
23+
public class EncodeAndDecodeTree {
24+
private var encodeStr = ""
25+
private var ret: [String] = []
26+
27+
public init() {}
28+
29+
public func encode(_ root: TreeNode?) -> String {
30+
encodeIt(root)
31+
32+
return encodeStr
33+
}
34+
35+
public func decode(_ data: String) -> TreeNode? {
36+
var s = data
37+
while (s.contains(" ")) {
38+
let index = s.index(of: " ")
39+
let endIndex = s.index(before: index)
40+
let element = s[s.startIndex...endIndex]
41+
ret.append(element)
42+
let range = ClosedRange(uncheckedBounds: (lower: s.startIndex, upper: index))
43+
s.removeSubrange(range)
44+
}
45+
46+
if ret.count == 0 {
47+
return nil
48+
}
49+
50+
var dep = 0
51+
let root = decodeIt(&dep)
52+
53+
return root
54+
}
55+
56+
private func getNode(_ element: String) -> TreeNode? {
57+
if element == "#" {
58+
return nil
59+
}
60+
61+
return TreeNode(element)
62+
}
63+
64+
private func decodeIt(_ dep: inout Int) -> TreeNode? {
65+
guard let currentNode = getNode(ret[dep]) else {
66+
return nil
67+
}
68+
69+
dep += 1
70+
let left = decodeIt(&dep)
71+
dep += 1
72+
let right = decodeIt(&dep)
73+
74+
currentNode.left = left
75+
currentNode.right = right
76+
77+
return currentNode
78+
}
79+
80+
private func encodeIt(_ root: TreeNode?) {
81+
guard let root = root else {
82+
encodeStr += "# "
83+
return
84+
}
85+
86+
encodeStr += root.val + " "
87+
encodeIt(root.left)
88+
encodeIt(root.right)
89+
}
90+
}
91+
92+
extension String {
93+
func index(of target: Character) -> String.Index {
94+
var i = 0
95+
for c in self.characters {
96+
if c == target {
97+
return self.index(self.startIndex, offsetBy: i)
98+
}
99+
i += 1
100+
}
101+
102+
return self.endIndex
103+
}
104+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='ios'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//
2+
// EncodeAndDecodeTree.swift
3+
//
4+
//
5+
// Created by Kai Chen on 19/07/2017.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
public class TreeNode {
12+
public var val: String
13+
public var left: TreeNode?
14+
public var right: TreeNode?
15+
16+
public init(_ val: String, left: TreeNode? = nil, right: TreeNode? = nil) {
17+
self.val = val
18+
self.left = left
19+
self.right = right
20+
}
21+
}
22+
23+
public class EncodeAndDecodeTree {
24+
private var encodeStr = ""
25+
private var ret: [String] = []
26+
27+
public init() {}
28+
29+
public func encode(_ root: TreeNode?) -> String {
30+
encodeIt(root)
31+
32+
return encodeStr
33+
}
34+
35+
public func decode(_ data: String) -> TreeNode? {
36+
var s = data
37+
while (s.contains(" ")) {
38+
let index = s.index(of: " ")
39+
let endIndex = s.index(before: index)
40+
let element = s[s.startIndex...endIndex]
41+
ret.append(element)
42+
let range = ClosedRange(uncheckedBounds: (lower: s.startIndex, upper: index))
43+
s.removeSubrange(range)
44+
}
45+
46+
if ret.count == 0 {
47+
return nil
48+
}
49+
50+
var dep = 0
51+
let root = decodeIt(&dep)
52+
53+
return root
54+
}
55+
56+
private func getNode(_ element: String) -> TreeNode? {
57+
if element == "#" {
58+
return nil
59+
}
60+
61+
return TreeNode(element)
62+
}
63+
64+
private func decodeIt(_ dep: inout Int) -> TreeNode? {
65+
guard let currentNode = getNode(ret[dep]) else {
66+
return nil
67+
}
68+
69+
dep += 1
70+
let left = decodeIt(&dep)
71+
dep += 1
72+
let right = decodeIt(&dep)
73+
74+
currentNode.left = left
75+
currentNode.right = right
76+
77+
return currentNode
78+
}
79+
80+
private func encodeIt(_ root: TreeNode?) {
81+
guard let root = root else {
82+
encodeStr += "# "
83+
return
84+
}
85+
86+
encodeStr += root.val + " "
87+
encodeIt(root.left)
88+
encodeIt(root.right)
89+
}
90+
}
91+
92+
extension String {
93+
func index(of target: Character) -> String.Index {
94+
var i = 0
95+
for c in self.characters {
96+
if c == target {
97+
return self.index(self.startIndex, offsetBy: i)
98+
}
99+
i += 1
100+
}
101+
102+
return self.endIndex
103+
}
104+
}

Encode and Decode Tree/readme.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Encode and Decode Binary Tree
2+
3+
We need to design an algorithm to encode and decode a binary tree.
4+
* **Encode**: Convert a tree into a string that can be stored in the disk.
5+
* **Decode**: Given the encoded string, you need to convert it into a Tree.
6+
7+
For example, you may serialize the following tree
8+
9+
10+
as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
11+
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.
12+
13+
## Solution
14+
For example, given a tree like this
15+
> a
16+
> / \\
17+
>
18+
> b c
19+
>
20+
> ​ / \\
21+
> ​ d e
22+
23+
We can use inorder traversal to convert the tree into the string like this `a b # # c d # # e # #`
24+
25+
So, the idea is for the empty node, we use `#` to represent.
26+
27+
For the decode process, we can still use inorder to convert the string back to a tree.

swift-algorithm-club.xcworkspace/contents.xcworkspacedata

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)