all: fix broken markdown comments with missing or unwanted code blocks
[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 protected fun search_down(from: N, key: K): nullable N do
97 var cmp = key <=> from.key
98 if cmp == 0 then return from
99 if from.left != null and cmp < 0 then
100 return search_down(from.left.as(not null), key)
101 else if from.right != null then
102 return search_down(from.right.as(not null), key)
103 end
104 return null
105 end
106
107 # Get the node with the minimum key
108 # O(n) in worst case, average is O(h) with h: tree height
109 #
110 # var tree = new BinTreeMap[Int, String]
111 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
112 # assert tree.min == "n1"
113 fun min: E do
114 assert not_empty: root != null
115 return min_from(root.as(not null)).value
116 end
117
118 protected fun min_from(node: N): N do
119 if node.left == null then return node
120 return min_from(node.left.as(not null))
121 end
122
123 # Get the node with the maximum key
124 # O(n) in worst case, average is O(h) with h: tree height
125 #
126 # var tree = new BinTreeMap[Int, String]
127 # for i in [4, 2, 1, 5, 3, 6, 7, 8] do tree[i] = "n{i}"
128 # assert tree.max == "n8"
129 fun max: E do
130 assert not_empty: root != null
131 return max_from(root.as(not null)).value
132 end
133
134 protected fun max_from(node: N): N do
135 if node.right == null then return node
136 return max_from(node.right.as(not null))
137 end
138
139 # Insert a new node in tree using `key` and `item`
140 # O(n) in worst case, average is O(h) with h: tree height
141 #
142 # var tree = new BinTreeMap[Int, String]
143 # tree[1] = "n1"
144 # assert tree.max == "n1"
145 # tree[3] = "n3"
146 # assert tree.max == "n3"
147 redef fun []=(key, item) do
148 insert_node(new BinTreeNode[K, E](key, item))
149 end
150
151 protected fun insert_node(node: N) do
152 len += 1
153 if root == null then
154 root = node
155 else
156 shift_down(root.as(not null), node)
157 end
158 if first_node == null then
159 first_node = node
160 end
161 if last_node != null then
162 last_node.next = node
163 node.prev = last_node
164 end
165 last_node = node
166 end
167
168 # Push down the `node` in tree from a specified `from` index
169 protected fun shift_down(from, node: N) do
170 var cmp = node.key <=> from.key
171 if cmp < 0 then
172 if from.left == null then
173 from.left = node
174 node.parent = from
175 else
176 shift_down(from.left.as(not null), node)
177 end
178 else if cmp > 0 then
179 if from.right == null then
180 from.right = node
181 node.parent = from
182 else
183 shift_down(from.right.as(not null), node)
184 end
185 end
186 end
187
188 # Delete node at `key` (also return the deleted node value)
189 # O(n) in worst case, average is O(h) with h: tree height
190 #
191 # var tree = new BinTreeMap[Int, String]
192 # tree[1] = "n1"
193 # assert tree.max == "n1"
194 # tree[3] = "n3"
195 # assert tree.max == "n3"
196 # tree.delete(3)
197 # assert tree.max == "n1"
198 fun delete(key: K): nullable E do
199 assert is_empty: root != null
200 len -= 1
201 var node = search_down(root.as(not null), key)
202 if node == null then return null
203 if node.left == null then
204 transplant(node, node.right)
205 else if node.right == null then
206 transplant(node, node.left)
207 else
208 var min = min_from(node.right.as(not null))
209 if min.parent != node then
210 transplant(min, min.right)
211 min.right = node.right
212 min.right.parent = min
213 end
214 transplant(node, min)
215 min.left = node.left
216 min.left.parent = min
217 end
218 if first_node == node then
219 first_node = null
220 end
221 if last_node == node then
222 last_node = node.prev
223 last_node.next = null
224 else
225 node.prev.next = node.next
226 node.next.prev = node.prev
227 end
228 return node.value
229 end
230
231 # Swap a `node` with the `other` in this Tree
232 # note: Nodes parents are updated, children still untouched
233 protected fun transplant(node, other: nullable N) do
234 if node == null then return
235 if node.parent == null then
236 root = other
237 else if node == node.parent.left then
238 node.parent.left = other
239 else
240 node.parent.right = other
241 end
242 if other != null then other.parent = node.parent
243 end
244
245 # Perform left rotation on `node`
246 #
247 # ~~~raw
248 # N Y
249 # / \ > / \
250 # a Y N c
251 # / \ < / \
252 # b c a b
253 # ~~~
254 #
255 protected fun rotate_left(node: N) do
256 var y = node.right
257 node.right = y.left
258 if y.left != null then
259 y.left.parent = node
260 end
261 y.parent = node.parent
262 if node.parent == null then
263 root = y
264 else if node == node.parent.left then
265 node.parent.left = y
266 else
267 node.parent.right = y
268 end
269 y.left = node
270 node.parent = y
271 end
272
273 # Perform right rotation on `node`
274 #
275 # ~~~raw
276 # N Y
277 # / \ > / \
278 # a Y N c
279 # / \ < / \
280 # b c a b
281 # ~~~
282 #
283 protected fun rotate_right(node: N) do
284 var y = node.left
285 node.left = y.right
286 if y.right != null then
287 y.right.parent = node
288 end
289 y.parent = node.parent
290 if node.parent == null then
291 root = y
292 else if node == node.parent.right then
293 node.parent.right = y
294 else
295 node.parent.left = y
296 end
297 y.right = node
298 node.parent = y
299 end
300
301 # Sort the tree into an array
302 # O(n)
303 #
304 # var tree = new BinTreeMap[Int, String]
305 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
306 # assert tree.sort == ["n1", "n2", "n3", "n4", "n5"]
307 fun sort: Array[E] do
308 var sorted = new Array[E]
309 if root == null then return sorted
310 sort_down(root.as(not null), sorted)
311 return sorted
312 end
313
314 protected fun sort_down(node: N, sorted: Array[E]) do
315 if node.left != null then sort_down(node.left.as(not null), sorted)
316 sorted.add(node.value)
317 if node.right != null then sort_down(node.right.as(not null), sorted)
318 end
319
320 redef fun to_s do
321 var root = self.root
322 if root == null then return "[]"
323 return "[{print_tree(root)}]"
324 end
325
326 protected fun print_tree(node: N): String do
327 var s = new FlatBuffer
328 s.append(node.to_s)
329 if node.left != null then s.append(print_tree(node.left.as(not null)))
330 if node.right != null then s.append(print_tree(node.right.as(not null)))
331 return s.to_s
332 end
333
334 redef fun show_dot do
335 assert not_empty: root != null
336 var f = new OProcess("dot", "-Txlib")
337 f.write "digraph \{\n"
338 dot_down(root.as(not null), f)
339 f.write "\}\n"
340 f.close
341 end
342
343 protected fun dot_down(node: N, f: OProcess) do
344 if node.left != null then dot_down(node.left.as(not null), f)
345 f.write node.to_dot
346 if node.right != null then dot_down(node.right.as(not null), f)
347 end
348
349 # O(n)
350 #
351 # var tree = new BinTreeMap[Int, String]
352 # assert tree.length == 0
353 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
354 # assert tree.length == 5
355 redef fun length do return len
356
357 # Nodes are iterated in the same order in which they were added to the tree.
358 # O(n)
359 #
360 # var tree = new BinTreeMap[Int, String]
361 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
362 # var keys = new Array[Int]
363 # for k, v in tree do
364 # keys.add k
365 # end
366 # assert keys == [4, 2, 1, 5, 3]
367 redef fun iterator do return new BinTreeMapIterator[K, E](self)
368 end
369
370 # TreeNode used by BinTree
371 class BinTreeNode[K: Comparable, E]
372 super TreeNode[K, E]
373
374 private var prev: nullable BinTreeNode[K, E]
375 private var next: nullable BinTreeNode[K, E]
376
377 redef type N: BinTreeNode[K, E]
378
379 init(key: K, item: E) do
380 super(key, item)
381 end
382
383 private var left_node: nullable N = null
384
385 # `left` tree node child (null if node has no left child)
386 fun left: nullable N do return left_node
387
388 # set `left` child for this node (or null if left no child)
389 # ENSURE: node.key < key (only if node != null)
390 fun left=(node: nullable N) do
391 #assert node != null implies node.key < key
392 left_node = node
393 end
394
395 private var right_node: nullable N = null
396
397 # `right` tree node child (null if node has no right child)
398 fun right: nullable N do return right_node
399
400 # set `right` child for this node (or null if right no child)
401 # ENSURE: node.key < key (only if node != null)
402 fun right=(node: nullable N) do
403 #assert node != null implies node.key > key
404 right_node = node
405 end
406
407 # `parent` of the `parent` of this node (null if root)
408 fun grandparent: nullable N do
409 if parent == null then
410 return null
411 else
412 return parent.parent
413 end
414 end
415
416 # Other child of the `grandparent`
417 # `left` or `right` depends on the position of the current node against its parent
418 fun uncle: nullable N do
419 var g = grandparent
420 if g == null then
421 return null
422 else
423 if parent == g.left then
424 return g.right
425 else
426 return g.left
427 end
428 end
429 end
430
431 # Other child of the parent
432 # `left` or `right` depends on the position of the current node against its parent
433 fun sibling: nullable N do
434 if parent == null then
435 return null
436 else if self == parent.left then
437 return parent.right
438 else if self == parent.right then
439 return parent.left
440 else
441 return null
442 end
443 end
444
445 redef fun to_s do return "\{{key}: {value or else ""}\}"
446 end
447
448 private class BinTreeMapIterator[K: Comparable, E]
449 super MapIterator[K, E]
450
451 var current: nullable BinTreeNode[K, E]
452
453 init(tree: BinTreeMap[K, E]) do
454 current = tree.first_node
455 end
456
457 redef fun is_ok do return not current == null
458 redef fun next do current = current.next
459 redef fun item do return current.value
460 redef fun key do do return current.key
461 end