11package com.sunnychung.lib.multiplatform.bigtext.redblacktree
22
3- private enum class Color { RED , BLACK }
3+ enum class Color { RED , BLACK }
44
5- open class RedBlackTree <K : Comparable <K >, V > {
6- private inner class Node (
7- var key : K ,
8- var value : V ,
9- var color : Color ,
10- var left : Node ? = null ,
11- var right : Node ? = null ,
12- var parent : Node ? = null
13- )
5+ open class RedBlackTree <K : Comparable <K >, V > : Iterable <V > {
6+ inner class Node (
7+ key : K ,
8+ value : V ,
9+ color : Color ,
10+ left : Node ? = null ,
11+ right : Node ? = null ,
12+ parent : Node ? = null
13+ ) {
14+ var parent = parent
15+ internal set
16+ var right = right
17+ internal set
18+ var left = left
19+ internal set
20+ var color = color
21+ internal set
22+ var value = value
23+ internal set
24+ var key = key
25+ internal set
26+ }
1427
15- private var root: Node ? = null
28+ var root: Node ? = null
29+ protected set
1630
1731 // --- Public API ---
1832
33+ val isEmpty: Boolean
34+ get() = root == null
35+
36+ var size: Int = 0
37+ protected set
38+
1939 fun get (key : K ): V ? = searchNode(key)?.value
2040
2141 fun contains (key : K ): Boolean = searchNode(key) != null
2242
23- fun insert (key : K , value : V ) {
43+ open fun insert (key : K , value : V ): Node ? {
2444 var y: Node ? = null
2545 var x = root
2646
@@ -31,7 +51,7 @@ open class RedBlackTree<K : Comparable<K>, V> {
3151 key > x.key -> x = x.right
3252 else -> {
3353 x.value = value
34- return
54+ return null
3555 }
3656 }
3757 }
@@ -46,6 +66,8 @@ open class RedBlackTree<K : Comparable<K>, V> {
4666 }
4767
4868 insertFixup(z)
69+ ++ size
70+ return z
4971 }
5072
5173 fun remove (key : K ) {
@@ -59,6 +81,58 @@ open class RedBlackTree<K : Comparable<K>, V> {
5981 return result
6082 }
6183
84+ fun findNode (comparison : (Node ) -> Int ): Node ? {
85+ var x = root
86+ while (x != null ) {
87+ val comparisonResult = comparison(x)
88+ when {
89+ comparisonResult < 0 -> x = x.left
90+ comparisonResult > 0 -> x = x.right
91+ else -> return x
92+ }
93+ }
94+ return null
95+ }
96+
97+ fun find (comparison : (Node ) -> Int ): V ? = findNode(comparison)?.value
98+
99+ override fun iterator (): Iterator <V > = object : Iterator <V > {
100+ private val stack = mutableListOf<RedBlackTree <K , V >.Node > ()
101+ private var current = root
102+
103+ init {
104+ // Push all the way to the left
105+ while (current != null ) {
106+ stack.add(current!! )
107+ current = current!! .left
108+ }
109+ current = null
110+ }
111+
112+ override fun hasNext (): Boolean = stack.isNotEmpty()
113+
114+ override fun next (): V {
115+ if (! hasNext()) throw NoSuchElementException ()
116+ val node = stack.removeAt(stack.lastIndex)
117+ var nextNode = node.right
118+ while (nextNode != null ) {
119+ stack.add(nextNode)
120+ nextNode = nextNode.left
121+ }
122+ return node.value
123+ }
124+ }
125+
126+ fun visitInPostOrder (visitor : (Node ) -> Unit ) {
127+ fun visit (node : Node ? ) {
128+ if (node == null ) return
129+ visit(node.left)
130+ visit(node.right)
131+ visitor(node)
132+ }
133+ visit(root)
134+ }
135+
62136 // --- Internal helpers ---
63137
64138 private fun inOrder (node : Node ? , list : MutableList <Pair <K , V >>) {
@@ -81,7 +155,7 @@ open class RedBlackTree<K : Comparable<K>, V> {
81155 return null
82156 }
83157
84- private fun insertFixup (z : Node ) {
158+ protected fun insertFixup (z : Node ) {
85159 var z = z
86160 while (z.parent?.color == Color .RED ) {
87161 val p = z.parent!!
@@ -123,7 +197,8 @@ open class RedBlackTree<K : Comparable<K>, V> {
123197 root?.color = Color .BLACK
124198 }
125199
126- private fun transplant (u : Node , v : Node ? ) {
200+ protected open fun transplant (u : Node , v : Node ? ) {
201+ val uParent = u.parent
127202 if (u.parent == null ) {
128203 root = v
129204 } else if (u == u.parent?.left) {
@@ -132,6 +207,8 @@ open class RedBlackTree<K : Comparable<K>, V> {
132207 u.parent?.right = v
133208 }
134209 v?.parent = u.parent
210+ uParent?.let { n -> recompute(n) }
211+ // the recomputation of `v` is called outside
135212 }
136213
137214 private fun minimum (x : Node ): Node {
@@ -140,7 +217,7 @@ open class RedBlackTree<K : Comparable<K>, V> {
140217 return curr
141218 }
142219
143- private fun deleteNode (z : Node ) {
220+ open fun deleteNode (z : Node ) {
144221 var y = z
145222 var yOriginalColor = y.color
146223 var x: Node ? = null
@@ -150,10 +227,12 @@ open class RedBlackTree<K : Comparable<K>, V> {
150227 x = z.right
151228 xParent = z.parent
152229 transplant(z, z.right)
230+ xParent?.let { n -> recomputeBottomUp(n) }
153231 } else if (z.right == null ) {
154232 x = z.left
155233 xParent = z.parent
156234 transplant(z, z.left)
235+ xParent?.let { n -> recomputeBottomUp(n) }
157236 } else {
158237 y = minimum(z.right!! )
159238 yOriginalColor = y.color
@@ -170,13 +249,26 @@ open class RedBlackTree<K : Comparable<K>, V> {
170249 y.left = z.left
171250 y.left?.parent = y
172251 y.color = z.color
252+
253+ recomputeBottomUp(y)
173254 }
174255
175256 if (yOriginalColor == Color .BLACK ) {
176257 deleteFixup(x, xParent)
177258 }
259+ -- size
178260 }
179261
262+ protected open fun recomputeBottomUp (n : Node ) {
263+ var p: Node ? = n
264+ while (p != null ) {
265+ recompute(p)
266+ p = p.parent
267+ }
268+ }
269+
270+ protected open fun recompute (n : Node ) = Unit
271+
180272 /* *
181273 * x is the replacement node (may be null)
182274 * p is the parent of x (may be null if x == root)
@@ -248,8 +340,8 @@ open class RedBlackTree<K : Comparable<K>, V> {
248340 x?.color = Color .BLACK
249341 }
250342
251- private fun rotateLeft (x : Node ) {
252- val y = x.right ? : return
343+ protected open fun rotateLeft (x : Node ): Boolean {
344+ val y = x.right ? : return false
253345 x.right = y.left
254346 if (y.left != null ) y.left?.parent = x
255347 y.parent = x.parent
@@ -262,10 +354,11 @@ open class RedBlackTree<K : Comparable<K>, V> {
262354 }
263355 y.left = x
264356 x.parent = y
357+ return true
265358 }
266359
267- private fun rotateRight (x : Node ) {
268- val y = x.left ? : return
360+ protected open fun rotateRight (x : Node ): Boolean {
361+ val y = x.left ? : return false
269362 x.left = y.right
270363 if (y.right != null ) y.right?.parent = x
271364 y.parent = x.parent
@@ -278,6 +371,7 @@ open class RedBlackTree<K : Comparable<K>, V> {
278371 }
279372 y.right = x
280373 x.parent = y
374+ return true
281375 }
282376
283377 // --- For Testing Only ---
0 commit comments