Skip to content

Commit c5f482c

Browse files
authored
Merge pull request kodecocodes#375 from weihanglo/binary-search-tree
Update Binary search tree
2 parents 890756d + f47a45e commit c5f482c

File tree

7 files changed

+113
-98
lines changed

7 files changed

+113
-98
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ script:
1313
- xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests
1414
- xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests
1515
- xcodebuild test -project ./Boyer-Moore/Tests/Tests.xcodeproj -scheme Tests
16-
# - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests
16+
- xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests
1717
- xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests
1818
# - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests
1919
# - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests

Binary Search Tree/README.markdown

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Sometimes you don't want to look at just a single node, but at all of them.
5858
There are three ways to traverse a binary tree:
5959

6060
1. *In-order* (or *depth-first*): first look at the left child of a node, then at the node itself, and finally at its right child.
61-
2. *Pre-order*: first look at a node, then its left and right children.
61+
2. *Pre-order*: first look at a node, then its left and right children.
6262
3. *Post-order*: first look at the left and right children and process the node itself last.
6363

6464
Once again, this happens recursively.
@@ -133,7 +133,7 @@ public class BinarySearchTree<T: Comparable> {
133133
}
134134
```
135135

136-
This class describes just a single node, not the entire tree. It's a generic type, so the node can store any kind of data. It also has references to its `left` and `right` child nodes and a `parent` node.
136+
This class describes just a single node, not the entire tree. It's a generic type, so the node can store any kind of data. It also has references to its `left` and `right` child nodes and a `parent` node.
137137

138138
Here's how you'd use it:
139139

@@ -258,7 +258,7 @@ Here is the implementation of `search()`:
258258

259259
I hope the logic is clear: this starts at the current node (usually the root) and compares the values. If the search value is less than the node's value, we continue searching in the left branch; if the search value is greater, we dive into the right branch.
260260

261-
Of course, if there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree.
261+
Of course, if there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree.
262262

263263
> **Note:** In Swift that's very conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There's no need to explicitly check for this with an `if` statement.
264264
@@ -300,21 +300,21 @@ The first three lines all return the corresponding `BinaryTreeNode` object. The
300300
Remember there are 3 different ways to look at all nodes in the tree? Here they are:
301301

302302
```swift
303-
public func traverseInOrder(@noescape process: T -> Void) {
304-
left?.traverseInOrder(process)
303+
public func traverseInOrder(process: (T) -> Void) {
304+
left?.traverseInOrder(process: process)
305305
process(value)
306-
right?.traverseInOrder(process)
306+
right?.traverseInOrder(process: process)
307307
}
308-
309-
public func traversePreOrder(@noescape process: T -> Void) {
308+
309+
public func traversePreOrder(process: (T) -> Void) {
310310
process(value)
311-
left?.traversePreOrder(process)
312-
right?.traversePreOrder(process)
311+
left?.traversePreOrder(process: process)
312+
right?.traversePreOrder(process: process)
313313
}
314-
315-
public func traversePostOrder(@noescape process: T -> Void) {
316-
left?.traversePostOrder(process)
317-
right?.traversePostOrder(process)
314+
315+
public func traversePostOrder(process: (T) -> Void) {
316+
left?.traversePostOrder(process: process)
317+
right?.traversePostOrder(process: process)
318318
process(value)
319319
}
320320
```
@@ -339,11 +339,12 @@ This prints the following:
339339
You can also add things like `map()` and `filter()` to the tree. For example, here's an implementation of map:
340340

341341
```swift
342-
public func map(@noescape formula: T -> T) -> [T] {
342+
343+
public func map(formula: (T) -> T) -> [T] {
343344
var a = [T]()
344-
if let left = left { a += left.map(formula) }
345+
if let left = left { a += left.map(formula: formula) }
345346
a.append(formula(value))
346-
if let right = right { a += right.map(formula) }
347+
if let right = right { a += right.map(formula: formula) }
347348
return a
348349
}
349350
```
@@ -365,7 +366,7 @@ tree.toArray() // [1, 2, 5, 7, 9, 10]
365366
```
366367

367368
As an exercise for yourself, see if you can implement filter and reduce.
368-
369+
369370
### Deleting nodes
370371

371372
We can make the code much more readable by defining some helper functions.
@@ -395,7 +396,7 @@ We also need a function that returns the minimum and maximum of a node:
395396
}
396397
return node
397398
}
398-
399+
399400
public func maximum() -> BinarySearchTree {
400401
var node = self
401402
while case let next? = node.right {
@@ -411,30 +412,32 @@ The rest of the code is pretty self-explanatory:
411412
```swift
412413
@discardableResult public func remove() -> BinarySearchTree? {
413414
let replacement: BinarySearchTree?
414-
415+
415416
// Replacement for current node can be either biggest one on the left or
416417
// smallest one on the right, whichever is not nil
417-
if let left = left {
418-
replacement = left.maximum()
419-
} else if let right = right {
418+
if let right = right {
420419
replacement = right.minimum()
420+
} else if let left = left {
421+
replacement = left.maximum()
421422
} else {
422-
replacement = nil;
423+
replacement = nil
423424
}
424-
425-
replacement?.remove();
425+
426+
replacement?.remove()
426427

427428
// Place the replacement on current node's position
428-
replacement?.right = right;
429-
replacement?.left = left;
430-
reconnectParentTo(node:replacement);
431-
429+
replacement?.right = right
430+
replacement?.left = left
431+
right?.parent = replacement
432+
left?.parent = replacement
433+
reconnectParentTo(node:replacement)
434+
432435
// The current node is no longer part of the tree, so clean it up.
433436
parent = nil
434437
left = nil
435438
right = nil
436-
437-
return replacement;
439+
440+
return replacement
438441
}
439442
```
440443

@@ -574,7 +577,7 @@ if let node1 = tree.search(1) {
574577

575578
## The code (solution 2)
576579

577-
We've implemented the binary tree node as a class but you can also use an enum.
580+
We've implemented the binary tree node as a class but you can also use an enum.
578581

579582
The difference is reference semantics versus value semantics. Making a change to the class-based tree will update that same instance in memory. But the enum-based tree is immutable -- any insertions or deletions will give you an entirely new copy of the tree. Which one is best totally depends on what you want to use it for.
580583

@@ -588,7 +591,7 @@ public enum BinarySearchTree<T: Comparable> {
588591
}
589592
```
590593

591-
The enum has three cases:
594+
The enum has three cases:
592595

593596
- `Empty` to mark the end of a branch (the class-based version used `nil` references for this).
594597
- `Leaf` for a leaf node that has no children.
@@ -606,7 +609,7 @@ As usual, we'll implement most functionality recursively. We'll treat each case
606609
case let .Node(left, _, right): return left.count + 1 + right.count
607610
}
608611
}
609-
612+
610613
public var height: Int {
611614
switch self {
612615
case .Empty: return 0
@@ -623,7 +626,7 @@ Inserting new nodes looks like this:
623626
switch self {
624627
case .Empty:
625628
return .Leaf(newValue)
626-
629+
627630
case .Leaf(let value):
628631
if newValue < value {
629632
return .Node(.Leaf(newValue), value, .Empty)

Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class BinarySearchTree<T: Comparable> {
2222
public convenience init(array: [T]) {
2323
precondition(array.count > 0)
2424
self.init(value: array.first!)
25-
for v in array.dropFirst() {
25+
for v in array.dropFirst() {
2626
insert(value: v)
2727
}
2828
}
@@ -106,30 +106,32 @@ extension BinarySearchTree {
106106
*/
107107
@discardableResult public func remove() -> BinarySearchTree? {
108108
let replacement: BinarySearchTree?
109-
109+
110110
// Replacement for current node can be either biggest one on the left or
111111
// smallest one on the right, whichever is not nil
112-
if let left = left {
113-
replacement = left.maximum()
114-
} else if let right = right {
112+
if let right = right {
115113
replacement = right.minimum()
114+
} else if let left = left {
115+
replacement = left.maximum()
116116
} else {
117-
replacement = nil;
117+
replacement = nil
118118
}
119-
120-
replacement?.remove();
119+
120+
replacement?.remove()
121121

122122
// Place the replacement on current node's position
123-
replacement?.right = right;
124-
replacement?.left = left;
125-
reconnectParentTo(node:replacement);
126-
123+
replacement?.right = right
124+
replacement?.left = left
125+
right?.parent = replacement
126+
left?.parent = replacement
127+
reconnectParentTo(node:replacement)
128+
127129
// The current node is no longer part of the tree, so clean it up.
128130
parent = nil
129131
left = nil
130132
right = nil
131-
132-
return replacement;
133+
134+
return replacement
133135
}
134136

135137
private func reconnectParentTo(node: BinarySearchTree?) {
@@ -322,7 +324,7 @@ extension BinarySearchTree: CustomStringConvertible {
322324
}
323325
return s
324326
}
325-
327+
326328
public func toArray() -> [T] {
327329
return map { $0 }
328330
}

0 commit comments

Comments
 (0)