Skip to content

Commit f4fb2fc

Browse files
author
nghiahoang
committed
fix: SplayTree.remove is broken
1 parent bcd9eb3 commit f4fb2fc

File tree

4 files changed

+57
-229
lines changed

4 files changed

+57
-229
lines changed

Splay Tree/SplayTree.playground/Contents.swift

+7-26
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,10 @@
55
print("Hello, Swift 4!")
66
#endif
77

8-
let splayTree = SplayTree(value: 1)
9-
splayTree.insert(value: 2)
10-
splayTree.insert(value: 10)
11-
splayTree.insert(value: 6)
12-
13-
splayTree.remove(value: 10)
14-
splayTree.remove(value: 6)
15-
16-
splayTree.insert(value: 55)
17-
splayTree.insert(value: 559)
18-
splayTree.remove(value: 2)
19-
splayTree.remove(value: 1)
20-
splayTree.remove(value: 55)
21-
splayTree.remove(value: 559)
22-
23-
splayTree.insert(value: 1843000)
24-
splayTree.insert(value: 1238)
25-
splayTree.insert(value: -1)
26-
splayTree.insert(value: 87)
27-
28-
splayTree.minimum()
29-
splayTree.maximum()
30-
31-
32-
33-
8+
var tree = SplayTree<Int>(value: 0)
9+
tree.insert(value: 2)
10+
tree.insert(value: 3)
11+
tree.insert(value: 4)
12+
tree.insert(value: 7)
13+
_ = tree.search(value: 2)
14+
tree.remove(value: 2)

Splay Tree/SplayTree.playground/Sources/SplayTree.swift

+22-100
Original file line numberDiff line numberDiff line change
@@ -289,120 +289,42 @@ extension Node {
289289
- Node Resulting from the deletion and the splaying of the removed node
290290

291291
*/
292-
public func remove(value: T) -> Node<T>? {
293-
let replacement: Node<T>?
292+
fileprivate func remove(value: T) -> Node<T>? {
293+
guard let target = search(value: value) else { return self }
294294

295-
if let v = self.value, v == value {
295+
if let left = target.left, let right = target.right {
296+
let largestOfLeftChild = left.maximum()
297+
left.parent = nil
298+
right.parent = nil
296299

297-
var parentToSplay: Node<T>?
298-
if let left = left {
299-
if let right = right {
300-
301-
replacement = removeNodeWithTwoChildren(left, right)
302-
303-
if let replacement = replacement,
304-
let replacementParent = replacement.parent,
305-
replacementParent.value != self.value {
306-
307-
parentToSplay = replacement.parent
308-
309-
} else if self.parent != nil {
310-
parentToSplay = self.parent
311-
} else {
312-
parentToSplay = replacement
313-
}
314-
315-
} else {
316-
// This node only has a left child. The left child replaces the node.
317-
replacement = left
318-
if self.parent != nil {
319-
parentToSplay = self.parent
320-
} else {
321-
parentToSplay = replacement
322-
}
323-
}
324-
} else if let right = right {
325-
// This node only has a right child. The right child replaces the node.
326-
replacement = right
327-
if self.parent != nil {
328-
parentToSplay = self.parent
329-
} else {
330-
parentToSplay = replacement
331-
}
332-
} else {
333-
// This node has no children. We just disconnect it from its parent.
334-
replacement = nil
335-
parentToSplay = parent
336-
}
337-
338-
reconnectParentTo(node: replacement)
300+
SplayOperation.splay(node: largestOfLeftChild)
301+
largestOfLeftChild.right = right
339302

340-
// performs the splay operation
341-
if let parentToSplay = parentToSplay {
342-
SplayOperation.splay(node: parentToSplay)
343-
}
303+
return largestOfLeftChild
344304

345-
// The current node is no longer part of the tree, so clean it up.
346-
parent = nil
347-
left = nil
348-
right = nil
305+
} else if let left = target.left {
306+
replace(node: target, with: left)
307+
return left
349308

350-
return parentToSplay
309+
} else if let right = target.right {
310+
replace(node: target, with: right)
311+
return right
351312

352-
} else if let v = self.value, value < v {
353-
if left != nil {
354-
return left!.remove(value: value)
355-
} else {
356-
let node = self
357-
SplayOperation.splay(node: node)
358-
return node
359-
360-
}
361313
} else {
362-
if right != nil {
363-
return right?.remove(value: value)
364-
} else {
365-
let node = self
366-
SplayOperation.splay(node: node)
367-
return node
368-
369-
}
314+
return nil
370315
}
371316
}
372317

373-
private func removeNodeWithTwoChildren(_ left: Node, _ right: Node) -> Node {
374-
// This node has two children. It must be replaced by the smallest
375-
// child that is larger than this node's value, which is the leftmost
376-
// descendent of the right child.
377-
let successor = right.minimum()
318+
private func replace(node: Node<T>, with newNode: Node<T>?) {
319+
guard let sourceParent = sourceNode.parent else { return }
378320

379-
// Connect our left child with the new node.
380-
successor.left = left
381-
left.parent = successor
382-
383-
// Connect our right child with the new node. If the right child does
384-
// not have any left children of its own, then the in-order successor
385-
// *is* the right child.
386-
if right !== successor {
387-
successor.right = right
388-
right.parent = successor
321+
if sourceNode.isLeftChild {
322+
sourceParent.left = newNode
389323
} else {
390-
successor.right = nil
324+
sourceParent.right = newNode
391325
}
392326

393-
// And finally, connect the successor node to our parent.
394-
return successor
395-
}
396-
397-
private func reconnectParentTo(node: Node?) {
398-
if let parent = parent {
399-
if isLeftChild {
400-
parent.left = node
401-
} else {
402-
parent.right = node
403-
}
404-
}
405-
node?.parent = parent
327+
newNode?.parent = sourceParent
406328
}
407329
}
408330

Splay Tree/SplayTree.swift

+23-101
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public enum SplayOperation {
4444
- Returns
4545
- Operation Case zigZag - zigZig - zig
4646
*/
47-
public static func operation<T: Comparable>(forNode node: Node<T>) -> SplayOperation {
47+
public static func operation<T>(forNode node: Node<T>) -> SplayOperation {
4848

4949
if let parent = node.parent, let _ = parent.parent {
5050
if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) {
@@ -289,120 +289,42 @@ extension Node {
289289
- Node Resulting from the deletion and the splaying of the removed node
290290

291291
*/
292-
public func remove(value: T) -> Node<T>? {
293-
let replacement: Node<T>?
292+
fileprivate func remove(value: T) -> Node<T>? {
293+
guard let target = search(value: value) else { return self }
294294

295-
if let v = self.value, v == value {
295+
if let left = target.left, let right = target.right {
296+
let largestOfLeftChild = left.maximum()
297+
left.parent = nil
298+
right.parent = nil
296299

297-
var parentToSplay: Node<T>?
298-
if let left = left {
299-
if let right = right {
300-
301-
replacement = removeNodeWithTwoChildren(left, right)
302-
303-
if let replacement = replacement,
304-
let replacementParent = replacement.parent,
305-
replacementParent.value != self.value {
306-
307-
parentToSplay = replacement.parent
308-
309-
} else if self.parent != nil {
310-
parentToSplay = self.parent
311-
} else {
312-
parentToSplay = replacement
313-
}
314-
315-
} else {
316-
// This node only has a left child. The left child replaces the node.
317-
replacement = left
318-
if self.parent != nil {
319-
parentToSplay = self.parent
320-
} else {
321-
parentToSplay = replacement
322-
}
323-
}
324-
} else if let right = right {
325-
// This node only has a right child. The right child replaces the node.
326-
replacement = right
327-
if self.parent != nil {
328-
parentToSplay = self.parent
329-
} else {
330-
parentToSplay = replacement
331-
}
332-
} else {
333-
// This node has no children. We just disconnect it from its parent.
334-
replacement = nil
335-
parentToSplay = parent
336-
}
300+
SplayOperation.splay(node: largestOfLeftChild)
301+
largestOfLeftChild.right = right
337302

338-
reconnectParentTo(node: replacement)
303+
return largestOfLeftChild
339304

340-
// performs the splay operation
341-
if let parentToSplay = parentToSplay {
342-
SplayOperation.splay(node: parentToSplay)
343-
}
305+
} else if let left = target.left {
306+
replace(node: target, with: left)
307+
return left
344308

345-
// The current node is no longer part of the tree, so clean it up.
346-
parent = nil
347-
left = nil
348-
right = nil
349-
350-
return parentToSplay
309+
} else if let right = target.right {
310+
replace(node: target, with: right)
311+
return right
351312

352-
} else if let v = self.value, value < v {
353-
if left != nil {
354-
return left!.remove(value: value)
355-
} else {
356-
let node = self
357-
SplayOperation.splay(node: node)
358-
return node
359-
360-
}
361313
} else {
362-
if right != nil {
363-
return right?.remove(value: value)
364-
} else {
365-
let node = self
366-
SplayOperation.splay(node: node)
367-
return node
368-
369-
}
314+
return nil
370315
}
371316
}
372317

373-
private func removeNodeWithTwoChildren(_ left: Node, _ right: Node) -> Node {
374-
// This node has two children. It must be replaced by the smallest
375-
// child that is larger than this node's value, which is the leftmost
376-
// descendent of the right child.
377-
let successor = right.minimum()
318+
private func replace(node: Node<T>, with newNode: Node<T>?) {
319+
guard let sourceParent = sourceNode.parent else { return }
378320

379-
// Connect our left child with the new node.
380-
successor.left = left
381-
left.parent = successor
382-
383-
// Connect our right child with the new node. If the right child does
384-
// not have any left children of its own, then the in-order successor
385-
// *is* the right child.
386-
if right !== successor {
387-
successor.right = right
388-
right.parent = successor
321+
if sourceNode.isLeftChild {
322+
sourceParent.left = newNode
389323
} else {
390-
successor.right = nil
324+
sourceParent.right = newNode
391325
}
392326

393-
// And finally, connect the successor node to our parent.
394-
return successor
395-
}
396-
397-
private func reconnectParentTo(node: Node?) {
398-
if let parent = parent {
399-
if isLeftChild {
400-
parent.left = node
401-
} else {
402-
parent.right = node
403-
}
404-
}
405-
node?.parent = parent
327+
newNode?.parent = sourceParent
406328
}
407329
}
408330

Splay Tree/readme.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,11 @@ To insert a value:
102102

103103
To delete a value:
104104

105-
- Delete it as in a binary search tree
106-
- Splay the parent of the removed node to the root
105+
- Perform search for the value, after performed search function if the tree contains the value, it'll be the root of the new tree.
106+
- If the tree has only left child, change left child to the root of the tree, remove the old root node
107+
- If the tree has only right child, change right child to the root of the tree, remove the old root node
108+
- Else, the tree has both two children, set parent of two children to nil, so that they're two new trees (left-tree and right-tree).
109+
- Splay the minimum node of right-tree (or minimum node of left-tree), then set left-tree as left child of new root of right-tree (or set right-tree as right child of new root of left-tree), return right-tree
107110

108111
### Search
109112

0 commit comments

Comments
 (0)