mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 09:24:36 +00:00
98 lines
2.4 KiB
Nim
98 lines
2.4 KiB
Nim
#
|
|
#
|
|
# Nim's Runtime Library
|
|
# (c) Copyright 2012 Andreas Rumpf
|
|
#
|
|
# See the file "copying.txt", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
# not really an AVL tree anymore, but still balanced ...
|
|
|
|
template isBottom(n: PAvlNode): bool = n.link[0] == n
|
|
|
|
proc lowGauge(n: PAvlNode): int =
|
|
var it = n
|
|
while not isBottom(it):
|
|
result = it.key
|
|
it = it.link[0]
|
|
|
|
proc highGauge(n: PAvlNode): int =
|
|
result = -1
|
|
var it = n
|
|
while not isBottom(it):
|
|
result = it.upperBound
|
|
it = it.link[1]
|
|
|
|
proc find(root: PAvlNode, key: int): PAvlNode =
|
|
var it = root
|
|
while not isBottom(it):
|
|
if it.key == key: return it
|
|
it = it.link[ord(it.key <% key)]
|
|
|
|
proc inRange(root: PAvlNode, key: int): PAvlNode =
|
|
var it = root
|
|
while not isBottom(it):
|
|
if it.key <=% key and key <% it.upperBound: return it
|
|
it = it.link[ord(it.key <% key)]
|
|
|
|
proc skew(t: var PAvlNode) =
|
|
if t.link[0].level == t.level:
|
|
var temp = t
|
|
t = t.link[0]
|
|
temp.link[0] = t.link[1]
|
|
t.link[1] = temp
|
|
|
|
proc split(t: var PAvlNode) =
|
|
if t.link[1].link[1].level == t.level:
|
|
var temp = t
|
|
t = t.link[1]
|
|
temp.link[1] = t.link[0]
|
|
t.link[0] = temp
|
|
inc t.level
|
|
|
|
proc add(a: var MemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} =
|
|
if t.isBottom:
|
|
t = allocAvlNode(a, key, upperBound)
|
|
else:
|
|
if key <% t.key:
|
|
when defined(avlcorruption):
|
|
if t.link[0] == nil:
|
|
cprintf("bug here %p\n", t)
|
|
add(a, t.link[0], key, upperBound)
|
|
elif key >% t.key:
|
|
when defined(avlcorruption):
|
|
if t.link[1] == nil:
|
|
cprintf("bug here B %p\n", t)
|
|
add(a, t.link[1], key, upperBound)
|
|
else:
|
|
sysAssert false, "key already exists"
|
|
skew(t)
|
|
split(t)
|
|
|
|
proc del(a: var MemRegion, t: var PAvlNode, x: int) {.benign.} =
|
|
if isBottom(t): return
|
|
a.last = t
|
|
if x <% t.key:
|
|
del(a, t.link[0], x)
|
|
else:
|
|
a.deleted = t
|
|
del(a, t.link[1], x)
|
|
if t == a.last and not isBottom(a.deleted) and x == a.deleted.key:
|
|
a.deleted.key = t.key
|
|
a.deleted.upperBound = t.upperBound
|
|
a.deleted = getBottom(a)
|
|
t = t.link[1]
|
|
deallocAvlNode(a, a.last)
|
|
elif t.link[0].level < t.level-1 or
|
|
t.link[1].level < t.level-1:
|
|
dec t.level
|
|
if t.link[1].level > t.level:
|
|
t.link[1].level = t.level
|
|
skew(t)
|
|
skew(t.link[1])
|
|
skew(t.link[1].link[1])
|
|
split(t)
|
|
split(t.link[1])
|
|
|