Files
prog8/examples/pointers/binarytree.p8
2025-06-13 23:20:15 +02:00

226 lines
5.6 KiB
Lua

; Binary Tree.
%import math
%import textio
main {
sub start() {
repeat 20 {
btree.add(math.rndw() % 1000)
}
txt.print("sorted values: ")
btree.print_tree_inorder()
txt.print("'tree' form:\n")
btree.print_tree_preorder()
txt.print("203 in tree? ")
txt.print_bool(btree.contains(203))
txt.print("\n204 in tree? ")
txt.print_bool(btree.contains(204))
txt.print("\n605 in tree? ")
txt.print_bool(btree.contains(605))
txt.print("\n606 in tree? ")
txt.print_bool(btree.contains(606))
txt.nl()
txt.print("REMOVING 9999:\n")
btree.remove(9999)
; btree.remove(97)
; btree.remove(187)
; btree.remove(203)
; btree.remove(275)
; btree.remove(321)
; btree.remove(520)
; btree.remove(562)
; btree.remove(606)
; btree.remove(716)
; btree.remove(794)
; txt.print("sorted values: ")
; btree.print_tree_inorder()
; txt.print("'tree' form:\n")
; btree.print_tree_preorder()
}
}
btree {
struct Node {
^^Node left
^^Node right
uword value
}
^^Node root = 0
sub add(uword value) {
^^Node node = arena.alloc(sizeof(Node))
node.value = value
node.left = node.right = 0
if root==0
root=node
else {
^^Node parent = root
repeat {
if parent.value >= value {
if parent.left
parent = parent.left
else {
parent.left = node
return
}
} else {
if parent.right
parent = parent.right
else {
parent.right = node
return
}
}
}
}
}
sub contains(uword value) -> bool {
^^Node r = root
while r {
if r.value==value
return true
if r.value>value
r = r.left
else
r = r.right
}
return false
}
sub remove(uword value) {
; note: we don't deallocate the memory from the node, for simplicity sake
txt.print("REMOVE ")
txt.print_uw(value)
txt.nl()
^^Node n = root
^^Node parent = 0
while n {
if n.value==value {
txt.print("FOUND!\n")
if n.left==0
replacechild(parent, n, n.right)
else if n.right==0
replacechild(parent, n, n.left)
else {
; Both left & right subtrees are present.
; N = node to delete.
; Find N's successor S. (N's right subtree's minimum element)
; Attach N's left subtree to S.left (S doesn't have a left child)
; Attach N's right subtree to Parent in place of N.
txt.print("NEED SUCCESSOR OF ")
txt.print_uw(n)
txt.print(": ")
txt.print_uw(n.value)
txt.nl()
^^Node successor = find_successor(n)
successor.left = n.left
replacechild(parent, n, n.right)
}
return
}
parent = n
if n.value>value
n = n.left
else
n = n.right
}
sub find_successor(^^Node p) -> ^^Node {
txt.print("SUCCESSOR OF ")
txt.print_uw(p)
txt.print(": ")
txt.print_uw(p.value)
txt.nl()
; ^^Node succ = p
; p = p.right
; while p!=0 {
; succ = p
; p = p.left
; txt.print("SUCC ")
; txt.print_uw(p)
; txt.nl()
; }
return 0
}
sub replacechild(^^Node p, ^^Node child, ^^Node newchild) {
if p.left==child
p.left = newchild
else
p.right = newchild
}
}
sub print_tree_inorder() {
if root
print_tree(root)
txt.nl()
sub print_tree(^^Node r) {
if r.left {
sys.pushw(r)
print_tree(r.left)
r = sys.popw()
}
txt.print_uw(r.value)
txt.print(", ")
if r.right {
sys.pushw(r)
print_tree(r.right)
r = sys.popw()
}
}
}
sub print_tree_preorder() {
if root
print_tree(root,0)
txt.nl()
sub print_tree(^^Node r, ubyte depth) {
repeat depth txt.print(" ")
txt.print_uw(r.value)
txt.nl()
if r.left {
sys.pushw(r)
sys.push(depth)
print_tree(r.left, depth+1)
depth = sys.pop()
r = sys.popw()
}
if r.right {
sys.pushw(r)
sys.push(depth)
print_tree(r.right, depth+1)
depth = sys.pop()
r = sys.popw()
}
}
}
}
arena {
; extremely trivial arena allocator (that never frees)
uword buffer = memory("arena", 2000, 0)
uword next = buffer
sub alloc(ubyte size) -> uword {
defer next += size
return next
}
}