tree.gno
5.58 Kb ยท 164 lines
1// Package cow provides a Copy-on-Write (CoW) AVL tree implementation.
2// This is a fork of gno.land/p/demo/avl that adds CoW functionality
3// while maintaining the original AVL tree interface and properties.
4//
5// Copy-on-Write creates a copy of a data structure only when it is modified,
6// while still presenting the appearance of a full copy. When a tree is cloned,
7// it initially shares all its nodes with the original tree. Only when a
8// modification is made to either the original or the clone are new nodes created,
9// and only along the path from the root to the modified node.
10//
11// Key features:
12// - O(1) cloning operation
13// - Minimal memory usage through structural sharing
14// - Full AVL tree functionality (self-balancing, ordered operations)
15// - Thread-safe for concurrent reads of shared structures
16//
17// While the CoW mechanism handles structural copying automatically, users need
18// to consider how to handle the values stored in the tree:
19//
20// 1. Simple Values (int, string, etc.):
21// - These are copied by value automatically
22// - No additional handling needed
23//
24// 2. Complex Values (structs, pointers):
25// - Only the reference is copied by default
26// - Users must implement their own deep copy mechanism if needed
27//
28// Example:
29//
30// // Create original tree
31// original := cow.NewTree()
32// original.Set("key1", "value1")
33//
34// // Create a clone - O(1) operation
35// clone := original.Clone()
36//
37// // Modify clone - only affected nodes are copied
38// clone.Set("key1", "modified")
39//
40// // Original remains unchanged
41// val, _ := original.Get("key1") // Returns "value1"
42package cow
43
44type IterCbFn func(key string, value any) bool
45
46//----------------------------------------
47// Tree
48
49// The zero struct can be used as an empty tree.
50type Tree struct {
51 node *Node
52}
53
54// NewTree creates a new empty AVL tree.
55func NewTree() *Tree {
56 return &Tree{
57 node: nil,
58 }
59}
60
61// Size returns the number of key-value pair in the tree.
62func (tree *Tree) Size() int {
63 return tree.node.Size()
64}
65
66// Has checks whether a key exists in the tree.
67// It returns true if the key exists, otherwise false.
68func (tree *Tree) Has(key string) (has bool) {
69 return tree.node.Has(key)
70}
71
72// Get retrieves the value associated with the given key.
73// It returns the value and a boolean indicating whether the key exists.
74func (tree *Tree) Get(key string) (value any, exists bool) {
75 _, value, exists = tree.node.Get(key)
76 return
77}
78
79// GetByIndex retrieves the key-value pair at the specified index in the tree.
80// It returns the key and value at the given index.
81func (tree *Tree) GetByIndex(index int) (key string, value any) {
82 return tree.node.GetByIndex(index)
83}
84
85// Set inserts a key-value pair into the tree.
86// If the key already exists, the value will be updated.
87// It returns a boolean indicating whether the key was newly inserted or updated.
88func (tree *Tree) Set(key string, value any) (updated bool) {
89 newnode, updated := tree.node.Set(key, value)
90 tree.node = newnode
91 return updated
92}
93
94// Remove removes a key-value pair from the tree.
95// It returns the removed value and a boolean indicating whether the key was found and removed.
96func (tree *Tree) Remove(key string) (value any, removed bool) {
97 newnode, _, value, removed := tree.node.Remove(key)
98 tree.node = newnode
99 return value, removed
100}
101
102// Iterate performs an in-order traversal of the tree within the specified key range.
103// It calls the provided callback function for each key-value pair encountered.
104// If the callback returns true, the iteration is stopped.
105func (tree *Tree) Iterate(start, end string, cb IterCbFn) bool {
106 return tree.node.TraverseInRange(start, end, true, true,
107 func(node *Node) bool {
108 return cb(node.Key(), node.Value())
109 },
110 )
111}
112
113// ReverseIterate performs a reverse in-order traversal of the tree within the specified key range.
114// It calls the provided callback function for each key-value pair encountered.
115// If the callback returns true, the iteration is stopped.
116func (tree *Tree) ReverseIterate(start, end string, cb IterCbFn) bool {
117 return tree.node.TraverseInRange(start, end, false, true,
118 func(node *Node) bool {
119 return cb(node.Key(), node.Value())
120 },
121 )
122}
123
124// IterateByOffset performs an in-order traversal of the tree starting from the specified offset.
125// It calls the provided callback function for each key-value pair encountered, up to the specified count.
126// If the callback returns true, the iteration is stopped.
127func (tree *Tree) IterateByOffset(offset int, count int, cb IterCbFn) bool {
128 return tree.node.TraverseByOffset(offset, count, true, true,
129 func(node *Node) bool {
130 return cb(node.Key(), node.Value())
131 },
132 )
133}
134
135// ReverseIterateByOffset performs a reverse in-order traversal of the tree starting from the specified offset.
136// It calls the provided callback function for each key-value pair encountered, up to the specified count.
137// If the callback returns true, the iteration is stopped.
138func (tree *Tree) ReverseIterateByOffset(offset int, count int, cb IterCbFn) bool {
139 return tree.node.TraverseByOffset(offset, count, false, true,
140 func(node *Node) bool {
141 return cb(node.Key(), node.Value())
142 },
143 )
144}
145
146// Equal returns true if the two trees contain the same key-value pairs.
147// WARNING: This is an expensive operation that recursively traverses the entire tree structure.
148// It should only be used in tests or when absolutely necessary.
149func (tree *Tree) Equal(other *Tree) bool {
150 if tree == nil || other == nil {
151 return tree == other
152 }
153 return tree.node.Equal(other.node)
154}
155
156// Clone creates a shallow copy of the tree
157func (tree *Tree) Clone() *Tree {
158 if tree == nil {
159 return nil
160 }
161 return &Tree{
162 node: tree.node,
163 }
164}