Skip to content

Instantly share code, notes, and snippets.

@slavo23
Created April 8, 2023 21:54
Show Gist options
  • Select an option

  • Save slavo23/99ed4d2f2ccf7cce6047c740e06079b7 to your computer and use it in GitHub Desktop.

Select an option

Save slavo23/99ed4d2f2ccf7cce6047c740e06079b7 to your computer and use it in GitHub Desktop.
Python example of a tree that uses arena allocation
from typing import TypeVar, List, Optional
from functools import partial
T = TypeVar('T')
class TreeNodeTy:
pass
class TreeNode(TreeNodeTy):
def __init__(
self,
value: T,
idx: int,
arena: List[TreeNodeTy],
left: Optional[int] = None,
right: Optional[int] = None,
):
self.arena_ref = arena
self.value = value
self.idx = idx
self.left, self.right = left, right
class Tree:
def __init__(self):
self.arena: List[TreeNode] = []
@property
def size(self) -> int:
return len(self.arena)
def __append(self, elem: TreeNode):
self.arena.append(elem)
return self.size - 1
def is_empty(self):
return not self.size
@classmethod
def from_list(cls, items: List[T]):
tree = cls()
for item in items:
tree.insert(item)
return tree
def to_list(self, traversal_type='inorder'):
traversal = []
def add_elem(elem: TreeNode):
traversal.append(elem.value)
def go(side, elem: TreeNode):
if child_index := getattr(elem, side):
traverse(child_index)
go_left = partial(go, 'left')
go_right = partial(go, 'right')
actions = {
'inorder': [go_left, add_elem, go_right],
'preorder': [add_elem, go_left, go_right],
'postorder': [go_left, go_right, add_elem]
}
def traverse(k=0):
curr = self.arena[k]
for action in actions[traversal_type]:
action(curr)
traverse(0)
return traversal
def insert(self, value):
new_node = TreeNode(
value=value,
arena=self.arena,
idx=self.size
)
if self.is_empty():
self.__append(new_node)
else:
curr_idx = 0
while True:
curr_node = self.arena[curr_idx]
curr_val = curr_node.value
left_idx = curr_node.left
right_idx = curr_node.right
if value > curr_val:
if right_idx is None:
curr_node.right = self.__append(new_node)
break
curr_idx = right_idx
else:
if left_idx is None:
curr_node.left = self.__append(new_node)
break
curr_idx = left_idx
xs = [10, 3, 9, 7, 1, 4, 5, 2, 6]
arena_tree = Tree.from_list(xs)
inorder_elems = arena_tree.to_list()
print(inorder_elems)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment