lib/standard/stream: Renamed streams for more explicit denomination
[nit.git] / lib / trees / bintree.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Binary Tree data-structure
16 # A binary tree is a tree data structure in which each node has at most two children
17 # (referred to as the left child and the right child).
18 # In a binary tree, the degree of each node can be at most two.
19 # Binary trees are used to implement binary search trees and binary heaps,
20 # and are used for efficient searching and sorting.
21 module bintree
22
23 import abstract_tree
24
25 # Binary Tree Map
26 #
27 # Properties:
28 # * unique root
29 # * node.left.key < node.key
30 # * node.right.key > node.key
31 # * no duplicates allowed
32 #
33 # Operations:
34 # * search average O(lg n) worst O(n)
35 # * insert average O(lg n) worst O(n)
36 # * delete average O(lg n) worst O(n)
37 #
38 # Usage:
39 # var tree = new BinTreeMap[Int, String]
40 # tree[1] = "n1"
41 # assert tree.min == "n1"
42 class BinTreeMap[K: Comparable, E]
43 super TreeMap[K, E]
44
45 redef type N: BinTreeNode[K, E]
46
47 private var len = 0
48 private var first_node: nullable BinTreeNode[K, E] = null
49 private var last_node: nullable BinTreeNode[K, E] = null
50
51 # O(n) in worst case, average is O(h) with h: tree height
52 #
53 # var tree = new BinTreeMap[Int, String]
54 # assert tree.is_empty
55 # tree[1] = "n1"
56 # assert not tree.is_empty
57 redef fun is_empty do return root == null
58
59 # O(n) in worst case, average is O(h) with h: tree height
60 #
61 # var tree = new BinTreeMap[Int, String]
62 # assert not tree.has_key(1)
63 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
64 # assert not tree.has_key(0)
65 # assert tree.has_key(2)
66 # assert not tree.has_key(6)
67 redef fun has_key(key: K): Bool do
68 if is_empty then return false
69 var res = search_down(root.as(not null), key)
70 if res != null then
71 cache_node = res
72 return true
73 end
74 return false
75 end
76
77 private var cache_node: nullable N = null
78
79 # Get the node value associated to `key`
80 # O(n) in worst case, average is O(h) with h: tree height
81 #
82 # var tree = new BinTreeMap[Int, String]
83 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
84 # assert tree.has_key(1)
85 # assert tree[1] == "n1"
86 # assert tree.has_key(1)
87 # assert tree[2] == "n2"
88 redef fun [](key: K): E do
89 assert not_empty: not is_empty
90 if cache_node != null and cache_node.key == key then return cache_node.value
91 var res = search_down(root.as(not null), key)
92 assert has_key: res != null
93 return res.value
94 end
95
96 # Search `key` in `from` and its children nodes.
97 protected fun search_down(from: N, key: K): nullable N do
98 var cmp = key <=> from.key
99 if cmp == 0 then return from
100 if from.left != null and cmp < 0 then
101 return search_down(from.left.as(not null), key)
102 else if from.right != null then
103 return search_down(from.right.as(not null), key)
104 end
105 return null
106 end
107
108 # Get the node with the minimum key
109 # O(n) in worst case, average is O(h) with h: tree height
110 #
111 # var tree = new BinTreeMap[Int, String]
112 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
113 # assert tree.min == "n1"
114 fun min: E do
115 assert not_empty: root != null
116 return min_from(root.as(not null)).value
117 end
118
119 # Get the left-most child from `node`.
120 protected fun min_from(node: N): N do
121 if node.left == null then return node
122 return min_from(node.left.as(not null))
123 end
124
125 # Get the node with the maximum key
126 # O(n) in worst case, average is O(h) with h: tree height
127 #
128 # var tree = new BinTreeMap[Int, String]
129 # for i in [4, 2, 1, 5, 3, 6, 7, 8] do tree[i] = "n{i}"
130 # assert tree.max == "n8"
131 fun max: E do
132 assert not_empty: root != null
133 return max_from(root.as(not null)).value
134 end
135
136 # Get the right-most child from `node`.
137 protected fun max_from(node: N): N do
138 if node.right == null then return node
139 return max_from(node.right.as(not null))
140 end
141
142 # Insert a new node in tree using `key` and `item`
143 # O(n) in worst case, average is O(h) with h: tree height
144 #
145 # var tree = new BinTreeMap[Int, String]
146 # tree[1] = "n1"
147 # assert tree.max == "n1"
148 # tree[3] = "n3"
149 # assert tree.max == "n3"
150 redef fun []=(key, item) do
151 insert_node(new BinTreeNode[K, E](key, item))
152 end
153
154 # Add `node` in the tree.
155 protected fun insert_node(node: N) do
156 len += 1
157 if root == null then
158 root = node
159 else
160 shift_down(root.as(not null), node)
161 end
162 if first_node == null then
163 first_node = node
164 end
165 if last_node != null then
166 last_node.next = node
167 node.prev = last_node
168 end
169 last_node = node
170 end
171
172 # Push down the `node` in tree from a specified `from` index
173 protected fun shift_down(from, node: N) do
174 var cmp = node.key <=> from.key
175 if cmp < 0 then
176 if from.left == null then
177 from.left = node
178 node.parent = from
179 else
180 shift_down(from.left.as(not null), node)
181 end
182 else if cmp > 0 then
183 if from.right == null then
184 from.right = node
185 node.parent = from
186 else
187 shift_down(from.right.as(not null), node)
188 end
189 end
190 end
191
192 # Delete node at `key` (also return the deleted node value)
193 # O(n) in worst case, average is O(h) with h: tree height
194 #
195 # var tree = new BinTreeMap[Int, String]
196 # tree[1] = "n1"
197 # assert tree.max == "n1"
198 # tree[3] = "n3"
199 # assert tree.max == "n3"
200 # tree.delete(3)
201 # assert tree.max == "n1"
202 fun delete(key: K): nullable E do
203 assert is_empty: root != null
204 len -= 1
205 var node = search_down(root.as(not null), key)
206 if node == null then return null
207 if node.left == null then
208 transplant(node, node.right)
209 else if node.right == null then
210 transplant(node, node.left)
211 else
212 var min = min_from(node.right.as(not null))
213 if min.parent != node then
214 transplant(min, min.right)
215 min.right = node.right
216 min.right.parent = min
217 end
218 transplant(node, min)
219 min.left = node.left
220 min.left.parent = min
221 end
222 if first_node == node then
223 first_node = null
224 end
225 if last_node == node then
226 last_node = node.prev
227 last_node.next = null
228 else
229 node.prev.next = node.next
230 node.next.prev = node.prev
231 end
232 return node.value
233 end
234
235 # Swap a `node` with the `other` in this Tree
236 # note: Nodes parents are updated, children still untouched
237 protected fun transplant(node, other: nullable N) do
238 if node == null then return
239 if node.parent == null then
240 root = other
241 else if node == node.parent.left then
242 node.parent.left = other
243 else
244 node.parent.right = other
245 end
246 if other != null then other.parent = node.parent
247 end
248
249 # Perform left rotation on `node`
250 #
251 # ~~~raw
252 # N Y
253 # / \ > / \
254 # a Y N c
255 # / \ < / \
256 # b c a b
257 # ~~~
258 #
259 protected fun rotate_left(node: N) do
260 var y = node.right
261 node.right = y.left
262 if y.left != null then
263 y.left.parent = node
264 end
265 y.parent = node.parent
266 if node.parent == null then
267 root = y
268 else if node == node.parent.left then
269 node.parent.left = y
270 else
271 node.parent.right = y
272 end
273 y.left = node
274 node.parent = y
275 end
276
277 # Perform right rotation on `node`
278 #
279 # ~~~raw
280 # N Y
281 # / \ > / \
282 # a Y N c
283 # / \ < / \
284 # b c a b
285 # ~~~
286 #
287 protected fun rotate_right(node: N) do
288 var y = node.left
289 node.left = y.right
290 if y.right != null then
291 y.right.parent = node
292 end
293 y.parent = node.parent
294 if node.parent == null then
295 root = y
296 else if node == node.parent.right then
297 node.parent.right = y
298 else
299 node.parent.left = y
300 end
301 y.right = node
302 node.parent = y
303 end
304
305 # Sort the tree into an array
306 # O(n)
307 #
308 # var tree = new BinTreeMap[Int, String]
309 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
310 # assert tree.sort == ["n1", "n2", "n3", "n4", "n5"]
311 fun sort: Array[E] do
312 var sorted = new Array[E]
313 if root == null then return sorted
314 sort_down(root.as(not null), sorted)
315 return sorted
316 end
317
318 # Sort the tree from `node` and place results in `sorted`.
319 protected fun sort_down(node: N, sorted: Array[E]) do
320 if node.left != null then sort_down(node.left.as(not null), sorted)
321 sorted.add(node.value)
322 if node.right != null then sort_down(node.right.as(not null), sorted)
323 end
324
325 redef fun to_s do
326 var root = self.root
327 if root == null then return "[]"
328 return "[{print_tree(root)}]"
329 end
330
331 # Print the tree starting from `node`.
332 protected fun print_tree(node: N): String do
333 var s = new FlatBuffer
334 s.append(node.to_s)
335 if node.left != null then s.append(print_tree(node.left.as(not null)))
336 if node.right != null then s.append(print_tree(node.right.as(not null)))
337 return s.to_s
338 end
339
340 redef fun show_dot do
341 assert not_empty: root != null
342 var f = new ProcessWriter("dot", "-Txlib")
343 f.write "digraph \{\n"
344 dot_down(root.as(not null), f)
345 f.write "\}\n"
346 f.close
347 end
348
349 # Translate the tree in dot format starting from `node`.
350 protected fun dot_down(node: N, f: ProcessWriter) do
351 if node.left != null then dot_down(node.left.as(not null), f)
352 f.write node.to_dot
353 if node.right != null then dot_down(node.right.as(not null), f)
354 end
355
356 # O(n)
357 #
358 # var tree = new BinTreeMap[Int, String]
359 # assert tree.length == 0
360 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
361 # assert tree.length == 5
362 redef fun length do return len
363
364 # Nodes are iterated in the same order in which they were added to the tree.
365 # O(n)
366 #
367 # var tree = new BinTreeMap[Int, String]
368 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
369 # var keys = new Array[Int]
370 # for k, v in tree do
371 # keys.add k
372 # end
373 # assert keys == [4, 2, 1, 5, 3]
374 redef fun iterator do return new BinTreeMapIterator[K, E](self)
375 end
376
377 # TreeNode used by BinTree
378 class BinTreeNode[K: Comparable, E]
379 super TreeNode[K, E]
380
381 private var prev: nullable BinTreeNode[K, E] = null
382 private var next: nullable BinTreeNode[K, E] = null
383
384 redef type N: BinTreeNode[K, E]
385
386 private var left_node: nullable N = null
387
388 # `left` tree node child (null if node has no left child)
389 fun left: nullable N do return left_node
390
391 # set `left` child for this node (or null if left no child)
392 # ENSURE: node.key < key (only if node != null)
393 fun left=(node: nullable N) do
394 #assert node != null implies node.key < key
395 left_node = node
396 end
397
398 private var right_node: nullable N = null
399
400 # `right` tree node child (null if node has no right child)
401 fun right: nullable N do return right_node
402
403 # set `right` child for this node (or null if right no child)
404 # ENSURE: node.key < key (only if node != null)
405 fun right=(node: nullable N) do
406 #assert node != null implies node.key > key
407 right_node = node
408 end
409
410 # `parent` of the `parent` of this node (null if root)
411 fun grandparent: nullable N do
412 if parent == null then
413 return null
414 else
415 return parent.parent
416 end
417 end
418
419 # Other child of the `grandparent`
420 # `left` or `right` depends on the position of the current node against its parent
421 fun uncle: nullable N do
422 var g = grandparent
423 if g == null then
424 return null
425 else
426 if parent == g.left then
427 return g.right
428 else
429 return g.left
430 end
431 end
432 end
433
434 # Other child of the parent
435 # `left` or `right` depends on the position of the current node against its parent
436 fun sibling: nullable N do
437 if parent == null then
438 return null
439 else if self == parent.left then
440 return parent.right
441 else if self == parent.right then
442 return parent.left
443 else
444 return null
445 end
446 end
447
448 redef fun to_s do return "\{{key}: {value or else ""}\}"
449 end
450
451 private class BinTreeMapIterator[K: Comparable, E]
452 super MapIterator[K, E]
453
454 var tree: BinTreeMap[K, E]
455 var current: nullable BinTreeNode[K, E] = null
456
457 init do current = tree.first_node
458
459 redef fun is_ok do return not current == null
460 redef fun next do current = current.next
461 redef fun item do return current.value
462 redef fun key do do return current.key
463 end