Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

node.gno

3.37 Kb · 138 lines
  1package trie
  2
  3// node is a single position in the trie tree
  4type node struct {
  5	char     byte    // node's char, unused in the root node
  6	value    any     // node's value, stored when isKey is true
  7	isKey    bool    // whether a key terminates at this node
  8	children []*node // child nodes, kept sorted ascending by char
  9}
 10
 11// childIndex returns the index of the child reached by byte c and whether such
 12// a child exists. When it does not exist, the returned index is the position at
 13// which a child with byte c must be inserted to keep children sorted.
 14func (n *node) childIndex(c byte) (int, bool) {
 15	lo := 0
 16	hi := len(n.children)
 17	for lo < hi {
 18		mid := (lo + hi) / 2
 19
 20		switch {
 21		case n.children[mid].char < c:
 22			lo = mid + 1
 23		case n.children[mid].char > c:
 24			hi = mid
 25		default:
 26			return mid, true
 27		}
 28	}
 29	return lo, false
 30}
 31
 32// get retrieves the value stored under key in the subtree rooted at n.
 33func (n *node) get(key string) (value any, exists bool) {
 34	cur := n
 35	for i := 0; i < len(key); i++ {
 36		idx, ok := cur.childIndex(key[i])
 37		if !ok {
 38			return nil, false
 39		}
 40
 41		cur = cur.children[idx]
 42	}
 43
 44	if !cur.isKey {
 45		return nil, false
 46	}
 47	return cur.value, true
 48}
 49
 50// set inserts or updates key with value. It returns true when the key already
 51// existed and its value updated, and false when it was newly inserted.
 52func (n *node) set(key string, value any) (updated bool) {
 53	cur := n
 54	for i := 0; i < len(key); i++ {
 55		c := key[i]
 56		idx, ok := cur.childIndex(c)
 57		if ok {
 58			cur = cur.children[idx]
 59			continue
 60		}
 61
 62		child := &node{char: c}
 63		cur.children = append(cur.children, nil)
 64		copy(cur.children[idx+1:], cur.children[idx:])
 65		cur.children[idx] = child
 66		cur = child
 67	}
 68
 69	if cur.isKey {
 70		cur.value = value
 71		return true
 72	}
 73
 74	cur.isKey = true
 75	cur.value = value
 76	return false
 77}
 78
 79// remove deletes key from the subtree rooted at n, pruning any nodes that no
 80// longer terminate a key and have no children. It returns the removed value and
 81// whether the key was found.
 82func (n *node) remove(key string) (value any, removed bool) {
 83	if key == "" {
 84		if !n.isKey {
 85			return nil, false
 86		}
 87
 88		value = n.value
 89		n.isKey = false
 90		n.value = nil
 91		return value, true
 92	}
 93
 94	idx, ok := n.childIndex(key[0])
 95	if !ok {
 96		return nil, false
 97	}
 98
 99	child := n.children[idx]
100	value, removed = child.remove(key[1:])
101	if removed && !child.isKey && len(child.children) == 0 {
102		n.children = append(n.children[:idx], n.children[idx+1:]...)
103	}
104	return value, removed
105}
106
107// inorder visits this node (when it terminates a key) and its whole subtree.
108// key is the full key spelled from the root to this node. When ascending is
109// true keys are produced in lexicographic order, otherwise in reverse. Because
110// a key always sorts before any key that extends it, the terminal value is
111// emitted before the children when ascending and after them when descending.
112// It returns true as soon as cb requests the walk to stop.
113func (n *node) inorder(key string, ascending bool, cb func(key string, value any) bool) (stop bool) {
114	if ascending {
115		if n.isKey && cb(key, n.value) {
116			return true
117		}
118
119		for _, c := range n.children {
120			if c.inorder(key+string([]byte{c.char}), ascending, cb) {
121				return true
122			}
123		}
124		return false
125	}
126
127	for i := len(n.children) - 1; i >= 0; i-- {
128		c := n.children[i]
129		if c.inorder(key+string([]byte{c.char}), ascending, cb) {
130			return true
131		}
132	}
133
134	if n.isKey && cb(key, n.value) {
135		return true
136	}
137	return false
138}