1
1
package geche
2
2
3
3
import (
4
+ "bytes"
4
5
"sync"
5
6
)
6
7
@@ -9,8 +10,8 @@ import (
9
10
const maxKeyLength = 512
10
11
11
12
type trieNode struct {
12
- // character
13
- c byte
13
+ // Node suffix. Single byte for most nodes, but can be longer for tail node.
14
+ b [] byte
14
15
// depth level
15
16
d int
16
17
@@ -33,7 +34,7 @@ type trieNode struct {
33
34
func (n * trieNode ) addToList (node * trieNode ) * trieNode {
34
35
curr := n
35
36
for {
36
- if node .c < curr .c {
37
+ if node .b [ 0 ] < curr .b [ 0 ] {
37
38
node .prev = curr .prev
38
39
node .next = curr
39
40
curr .prev = node
@@ -68,7 +69,7 @@ func (n *trieNode) addToList(node *trieNode) *trieNode {
68
69
func (n * trieNode ) removeFromList (c byte ) (* trieNode , bool ) {
69
70
curr := n
70
71
for {
71
- if curr .c == c {
72
+ if curr .b [ 0 ] == c {
72
73
if curr .prev != nil {
73
74
curr .prev .next = curr .next
74
75
}
@@ -125,21 +126,22 @@ func (kv *KV[V]) Set(key string, value V) {
125
126
return
126
127
}
127
128
129
+ keyb := []byte (key )
128
130
node := kv .trie
129
- for i := 0 ; i < len (key ); i ++ {
131
+ for len (keyb ) > 0 {
130
132
if node .down == nil {
131
133
// Creating new level.
132
134
node .down = make (map [byte ]* trieNode )
133
135
}
134
136
135
- next := node.down [key [ i ]]
137
+ next := node .down [keyb [ 0 ]]
136
138
if next == nil {
137
139
// Creating new node.
138
140
next = & trieNode {
139
- c : key [ i ] ,
141
+ b : keyb ,
140
142
d : node .d + 1 ,
141
143
}
142
- node.down [key [ i ]] = next
144
+ node .down [keyb [ 0 ]] = next
143
145
if node .nextLevelHead == nil {
144
146
node .nextLevelHead = next
145
147
} else {
@@ -149,15 +151,101 @@ func (kv *KV[V]) Set(key string, value V) {
149
151
node .nextLevelHead = head
150
152
}
151
153
}
154
+ } else if len (next .b ) == 1 {
155
+ // Single byte nodes are a simple case.
156
+ } else {
157
+ // Multi byte nodes require splitting.
158
+
159
+ // Removing node from the linked list.
160
+ head , empty := node .nextLevelHead .removeFromList (keyb [0 ])
161
+ if empty {
162
+ node .nextLevelHead = nil
163
+ } else if head != nil {
164
+ node .nextLevelHead = head
165
+ }
166
+
167
+ commonPrefixLen := commonPrefixLen (keyb , next .b )
168
+ for i := 0 ; i < commonPrefixLen ; i ++ {
169
+ // Creating new single-byte node.
170
+ newNode := & trieNode {
171
+ b : []byte {keyb [i ]},
172
+ d : node .d + 1 ,
173
+ down : make (map [byte ]* trieNode ),
174
+ }
175
+ node.down [keyb [i ]] = newNode
176
+ if node .nextLevelHead == nil {
177
+ node .nextLevelHead = newNode
178
+ } else {
179
+ head := node .nextLevelHead .addToList (newNode )
180
+ if head != nil {
181
+ node .nextLevelHead = head
182
+ }
183
+ }
184
+
185
+ node = newNode
186
+ }
187
+
188
+ if (bytes .Equal (next .b , keyb [:commonPrefixLen ]) && next .terminal ) || len (keyb ) == commonPrefixLen {
189
+ // If last node is end of key, or end of the node we are splitting, mark it as terminal.
190
+ node .terminal = true
191
+ }
192
+
193
+ // Adding removed node back.
194
+ if len (next .b ) > commonPrefixLen {
195
+ // Creating new suffix (potentially multi-byte) node.
196
+ newNode := & trieNode {
197
+ b : next .b [commonPrefixLen :],
198
+ d : node .d + 1 ,
199
+ terminal : true ,
200
+ }
201
+ node.down [next.b [commonPrefixLen ]] = newNode
202
+ node .nextLevelHead = newNode
203
+ }
204
+
205
+ // Adding new tail node.
206
+ if len (keyb ) > commonPrefixLen {
207
+ // Creating new suffix (potentially multi-byte) node.
208
+ newNode := & trieNode {
209
+ b : keyb [commonPrefixLen :],
210
+ d : node .d + 1 ,
211
+ terminal : true ,
212
+ }
213
+ node.down [keyb [commonPrefixLen ]] = newNode
214
+ if node .nextLevelHead == nil {
215
+ node .nextLevelHead = newNode
216
+ } else {
217
+ head := node .nextLevelHead .addToList (newNode )
218
+ if head != nil {
219
+ node .nextLevelHead = head
220
+ }
221
+ }
222
+ }
223
+
224
+ // keyb = keyb[commonPrefixLen:]
225
+ // continue
226
+ return
152
227
}
153
228
229
+ keyb = keyb [commonPrefixLen (keyb , next .b ):]
154
230
node = next
155
231
}
156
232
157
233
node .terminal = true
158
234
}
159
235
160
- // DFS starts with last node of the key prefix.
236
+ func commonPrefixLen (a , b []byte ) int {
237
+ i := 0
238
+ for ; i < len (a ) && i < len (b ); i ++ {
239
+ if a [i ] != b [i ] {
240
+ return i
241
+ }
242
+ }
243
+
244
+ return i
245
+ }
246
+
247
+ // Depth First Search starts with last node of the key prefix and traverses the trie,
248
+ // appending all terminal nodes to the result.
161
249
func (kv * KV [V ]) dfs (node * trieNode , prefix []byte ) ([]V , error ) {
162
250
res := []V {}
163
251
key := make ([]byte , len (prefix ), maxKeyLength )
@@ -177,6 +265,7 @@ func (kv *KV[V]) dfs(node *trieNode, prefix []byte) ([]V, error) {
177
265
return res , nil
178
266
}
179
267
268
+ // Instead of recursive DFS, we use stack-based approach.
180
269
stack := make ([]* trieNode , 0 , maxKeyLength )
181
270
stack = append (stack , node .nextLevelHead )
182
271
var (
@@ -190,18 +279,26 @@ func (kv *KV[V]) dfs(node *trieNode, prefix []byte) ([]V, error) {
190
279
break
191
280
}
192
281
282
+ // Pop the top node from the stack.
193
283
top = stack [len (stack )- 1 ]
194
284
stack = stack [:len (stack )- 1 ]
195
285
196
286
if top .d > prevDepth {
197
287
// We have descended to the next level.
198
- key = append (key , top .c )
288
+ key = append (key , top .b ... )
199
289
} else if top .d < prevDepth {
200
290
// We have ascended to the previous level.
201
- key = key [:len (key )- (prevDepth - top .d )]
202
- key [len (key )- 1 ] = top .c
291
+ key = key [:top .d ]
292
+ key [len (key )- 1 ] = top .b [0 ]
293
+ if len (top .b ) > 1 {
294
+ key = append (key , top .b [1 :]... )
295
+ }
203
296
} else {
204
- key [len (key )- 1 ] = top .c
297
+ key = key [:top .d ]
298
+ key [len (key )- 1 ] = top .b [0 ]
299
+ if len (top .b ) > 1 {
300
+ key = append (key , top .b [1 :]... )
301
+ }
205
302
}
206
303
prevDepth = top .d
207
304
@@ -237,6 +334,14 @@ func (kv *KV[V]) ListByPrefix(prefix string) ([]V, error) {
237
334
if next == nil {
238
335
return nil , nil
239
336
}
337
+ // If we reached a multibyte tail node, we can return its value,
338
+ // since tail nodes have no descendants.
339
+ if len (next .b ) > 1 && len (next .b ) >= len (prefix )- i {
340
+ if bytes .Equal (next .b [:len (prefix )- i ], []byte (prefix )[i :]) {
341
+ v , err := kv .data .Get (prefix + string (next .b [len (prefix )- i :]))
342
+ return []V {v }, err
343
+ }
344
+ }
240
345
node = next
241
346
}
242
347
@@ -255,6 +360,7 @@ func (kv *KV[V]) Del(key string) error {
255
360
256
361
node := kv .trie
257
362
stack := []* trieNode {}
363
+ found := false
258
364
for i := 0 ; i < len (key ); i ++ {
259
365
next := node.down [key [i ]]
260
366
if next == nil {
@@ -264,20 +370,31 @@ func (kv *KV[V]) Del(key string) error {
264
370
265
371
stack = append (stack , node )
266
372
node = next
373
+ if bytes .Equal (node .b , []byte (key )[i :]) {
374
+ if node .terminal {
375
+ found = true
376
+ }
377
+ break
378
+ }
267
379
}
268
380
381
+ if ! found {
382
+ // If we are here, the key does not exist.
383
+ return kv .data .Del (key )
384
+ }
385
+
269
386
node .terminal = false
270
387
271
388
// Go back the stack removing nodes with no descendants.
272
389
for i := len (stack ) - 1 ; i >= 0 ; i -- {
273
390
prev := stack [i ]
274
391
stack = stack [:i ]
275
392
if node .nextLevelHead == nil {
276
- head , empty := prev .nextLevelHead .removeFromList (node .c )
393
+ head , empty := prev .nextLevelHead .removeFromList (node .b [ 0 ] )
277
394
if head != nil || (head == nil && empty ) {
278
395
prev .nextLevelHead = head
279
396
}
280
- delete (prev .down , node .c )
397
+ delete (prev .down , node .b [ 0 ] )
281
398
}
282
399
283
400
if prev .terminal || len (prev .down ) > 0 && prev == kv .trie {
0 commit comments