1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
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.
29 # * node.left.key < node.key
30 # * node.right.key > node.key
31 # * no duplicates allowed
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)
39 # var tree = new BinTreeMap[Int, String]
41 # assert tree.min == "n1"
42 class BinTreeMap[K
: Comparable, E
]
45 redef type N
: BinTreeNode[K
, E
]
48 private var first_node
: nullable BinTreeNode[K
, E
] = null
49 private var last_node
: nullable BinTreeNode[K
, E
] = null
51 # O(n) in worst case, average is O(h) with h: tree height
53 # var tree = new BinTreeMap[Int, String]
54 # assert tree.is_empty
56 # assert not tree.is_empty
57 redef fun is_empty
do return root
== null
59 # O(n) in worst case, average is O(h) with h: tree height
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
)
77 private var cache_node
: nullable N
= null
79 # Get the node value associated to `key`
80 # O(n) in worst case, average is O(h) with h: tree height
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
96 protected fun search_down
(from
: N
, key
: K
): nullable N
do
97 if key
== from
.key
then return from
98 if from
.left
!= null and key
< from
.key
then
99 return search_down
(from
.left
.as(not null), key
)
100 else if from
.right
!= null then
101 return search_down
(from
.right
.as(not null), key
)
106 # Get the node with the minimum key
107 # O(n) in worst case, average is O(h) with h: tree height
109 # var tree = new BinTreeMap[Int, String]
110 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
111 # assert tree.min == "n1"
113 assert not_empty
: root
!= null
114 return min_from
(root
.as(not null)).value
117 protected fun min_from
(node
: N
): N
do
118 if node
.left
== null then return node
119 return min_from
(node
.left
.as(not null))
122 # Get the node with the maximum key
123 # O(n) in worst case, average is O(h) with h: tree height
125 # var tree = new BinTreeMap[Int, String]
126 # for i in [4, 2, 1, 5, 3, 6, 7, 8] do tree[i] = "n{i}"
127 # assert tree.max == "n8"
129 assert not_empty
: root
!= null
130 return max_from
(root
.as(not null)).value
133 protected fun max_from
(node
: N
): N
do
134 if node
.right
== null then return node
135 return max_from
(node
.right
.as(not null))
138 # Insert a new node in tree using `key` and `item`
139 # O(n) in worst case, average is O(h) with h: tree height
141 # var tree = new BinTreeMap[Int, String]
143 # assert tree.max == "n1"
145 # assert tree.max == "n3"
146 redef fun []=(key
, item
) do
147 insert_node
(new BinTreeNode[K
, E
](key
, item
))
150 protected fun insert_node
(node
: N
) do
155 shift_down
(root
.as(not null), node
)
157 if first_node
== null then
160 if last_node
!= null then
161 last_node
.next
= node
162 node
.prev
= last_node
167 # Push down the `node` in tree from a specified `from` index
168 protected fun shift_down
(from
, node
: N
) do
169 if node
.key
< from
.key
then
170 if from
.left
== null then
174 shift_down
(from
.left
.as(not null), node
)
176 else if node
.key
> from
.key
then
177 if from
.right
== null then
181 shift_down
(from
.right
.as(not null), node
)
186 # Delete node at `key` (also return the deleted node value)
187 # O(n) in worst case, average is O(h) with h: tree height
189 # var tree = new BinTreeMap[Int, String]
191 # assert tree.max == "n1"
193 # assert tree.max == "n3"
195 # assert tree.max == "n1"
196 fun delete
(key
: K
): nullable E
do
197 assert is_empty
: root
!= null
199 var node
= search_down
(root
.as(not null), key
)
200 if node
== null then return null
201 if node
.left
== null then
202 transplant
(node
, node
.right
)
203 else if node
.right
== null then
204 transplant
(node
, node
.left
)
206 var min
= min_from
(node
.right
.as(not null))
207 if min
.parent
!= node
then
208 transplant
(min
, min
.right
)
209 min
.right
= node
.right
210 min
.right
.parent
= min
212 transplant
(node
, min
)
214 min
.left
.parent
= min
216 if first_node
== node
then
219 if last_node
== node
then
220 last_node
= node
.prev
221 last_node
.next
= null
223 node
.prev
.next
= node
.next
224 node
.next
.prev
= node
.prev
229 # Swap a `node` with the `other` in this Tree
230 # note: Nodes parents are updated, children still untouched
231 protected fun transplant
(node
, other
: nullable N
) do
232 if node
== null then return
233 if node
.parent
== null then
235 else if node
== node
.parent
.left
then
236 node
.parent
.left
= other
238 node
.parent
.right
= other
240 if other
!= null then other
.parent
= node
.parent
243 # Perform left rotation on `node`
251 protected fun rotate_left
(node
: N
) do
254 if y
.left
!= null then
257 y
.parent
= node
.parent
258 if node
.parent
== null then
260 else if node
== node
.parent
.left
then
263 node
.parent
.right
= y
269 # Perform right rotation on `node`
277 protected fun rotate_right
(node
: N
) do
280 if y
.right
!= null then
281 y
.right
.parent
= node
283 y
.parent
= node
.parent
284 if node
.parent
== null then
286 else if node
== node
.parent
.right
then
287 node
.parent
.right
= y
295 # Sort the tree into an array
298 # var tree = new BinTreeMap[Int, String]
299 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
300 # assert tree.sort == ["n1", "n2", "n3", "n4", "n5"]
301 fun sort
: Array[E
] do
302 var sorted
= new Array[E
]
303 if root
== null then return sorted
304 sort_down
(root
.as(not null), sorted
)
308 protected fun sort_down
(node
: N
, sorted
: Array[E
]) do
309 if node
.left
!= null then sort_down
(node
.left
.as(not null), sorted
)
310 sorted
.add
(node
.value
)
311 if node
.right
!= null then sort_down
(node
.right
.as(not null), sorted
)
316 if root
== null then return "[]"
317 return "[{print_tree(root)}]"
320 protected fun print_tree
(node
: N
): String do
321 var s
= new FlatBuffer
323 if node
.left
!= null then s
.append
(print_tree
(node
.left
.as(not null)))
324 if node
.right
!= null then s
.append
(print_tree
(node
.right
.as(not null)))
328 redef fun show_dot
do
329 assert not_empty
: root
!= null
330 var f
= new OProcess("dot", "-Txlib")
331 f
.write
"digraph \{\n"
332 dot_down
(root
.as(not null), f
)
337 protected fun dot_down
(node
: N
, f
: OProcess) do
338 if node
.left
!= null then dot_down
(node
.left
.as(not null), f
)
340 if node
.right
!= null then dot_down
(node
.right
.as(not null), f
)
345 # var tree = new BinTreeMap[Int, String]
346 # assert tree.length == 0
347 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
348 # assert tree.length == 5
349 redef fun length
do return len
351 # Nodes are iterated in the same order in which they were added to the tree.
354 # var tree = new BinTreeMap[Int, String]
355 # for i in [4, 2, 1, 5, 3] do tree[i] = "n{i}"
356 # var keys = new Array[Int]
357 # for k, v in tree do
360 # assert keys == [4, 2, 1, 5, 3]
361 redef fun iterator
do return new BinTreeMapIterator[K
, E
](self)
364 # TreeNode used by BinTree
365 class BinTreeNode[K
: Comparable, E
]
368 private var prev
: nullable BinTreeNode[K
, E
]
369 private var next
: nullable BinTreeNode[K
, E
]
371 redef type SELF: BinTreeNode[K
, E
]
373 init(key
: K
, item
: E
) do
377 private var left_node
: nullable SELF = null
379 # `left` tree node child (null if node has no left child)
380 fun left
: nullable SELF do return left_node
382 # set `left` child for this node (or null if left no child)
383 # ENSURE: node.key < key (only if node != null)
384 fun left
=(node
: nullable SELF) do
385 assert node
!= null implies node
.key
< key
389 private var right_node
: nullable SELF = null
391 # `right` tree node child (null if node has no right child)
392 fun right
: nullable SELF do return right_node
394 # set `right` child for this node (or null if right no child)
395 # ENSURE: node.key < key (only if node != null)
396 fun right
=(node
: nullable SELF) do
398 assert node
.key
> key
403 # `parent` of the `parent` of this node (null if root)
404 fun grandparent
: nullable SELF do
405 if parent
== null then
412 # Other child of the `grandparent`
413 # `left` or `right` depends on the position of the current node against its parent
414 fun uncle
: nullable SELF do
419 if parent
== g
.left
then
427 # Other child of the parent
428 # `left` or `right` depends on the position of the current node against its parent
429 fun sibling
: nullable SELF do
430 if parent
== null then
432 else if self == parent
.left
then
434 else if self == parent
.right
then
441 redef fun to_s
do return "\{{key}: {value or else ""}\}"
444 private class BinTreeMapIterator[K
: Comparable, E
]
445 super MapIterator[K
, E
]
447 var current
: nullable BinTreeNode[K
, E
]
449 init(tree
: BinTreeMap[K
, E
]) do
450 current
= tree
.first_node
453 redef fun is_ok
do return not current
== null
454 redef fun next
do current
= current
.next
455 redef fun item
do return current
.value
456 redef fun key
do do return current
.key