From 44f405f343d44858aa46f352a85c60d7cc4649dd Mon Sep 17 00:00:00 2001 From: Milad Irannejad Date: Sat, 14 Dec 2024 15:11:30 -0500 Subject: [PATCH] Release 0.8.2 --- trie/binary.go | 68 +++---- trie/binary_test.go | 34 ++-- trie/patricia.go | 64 +++---- trie/patricia_test.go | 34 ++-- trie/radix.go | 418 ++++++++++++++++++++++++++++++++++++++++++ trie/radix_test.go | 78 ++++++++ 6 files changed, 596 insertions(+), 100 deletions(-) create mode 100644 trie/radix.go create mode 100644 trie/radix_test.go diff --git a/trie/binary.go b/trie/binary.go index c79cc6a..099195e 100644 --- a/trie/binary.go +++ b/trie/binary.go @@ -22,7 +22,7 @@ type binary[V any] struct { eqVal EqualFunc[V] } -// NewBinaryTrie creates a new Binary Trie tree. +// NewBinaryTrie creates a new binary trie tree. // // A trie, or prefix tree, is an ordered tree uses the digits in the keys where the keys are usually strings. // We can use any radix to decompose the keys into digits. @@ -110,12 +110,12 @@ func (t *binary[V]) _isRankOK() bool { return true } -// Size returns the number of key-value pairs in the Binary Trie. +// Size returns the number of key-value pairs in the binary trie. func (t *binary[V]) Size() int { return t.size } -// Height returns the height of the Binary Trie. +// Height returns the height of the binary trie. func (t *binary[V]) Height() int { return t._height(t.root.left) } @@ -128,12 +128,12 @@ func (t *binary[V]) _height(n *binaryNode[V]) int { return 1 + Max[int](t._height(n.left), t._height(n.right)) } -// IsEmpty returns true if the Binary Trie is empty. +// IsEmpty returns true if the binary trie is empty. func (t *binary[V]) IsEmpty() bool { return t.size == 0 } -// Put adds a new key-value pair to the Binary Trie. +// Put adds a new key-value pair to the binary trie. func (t *binary[V]) Put(key string, val V) { // Special case of empty string if key == "" { @@ -171,7 +171,7 @@ func (t *binary[V]) _put(n *binaryNode[V], key string, val V) *binaryNode[V] { return n } -// Get returns the value of a given key in the Binary Trie. +// Get returns the value of a given key in the binary trie. func (t *binary[V]) Get(key string) (V, bool) { // Special case of empty string if key == "" { @@ -197,7 +197,7 @@ func (t *binary[V]) _get(n *binaryNode[V], key string) (V, bool) { return t._get(n.right, key) } -// Delete removes a key-value pair from the Binary Trie. +// Delete removes a key-value pair from the binary trie. func (t *binary[V]) Delete(key string) (val V, ok bool) { // Special case of empty string if key == "" { @@ -234,7 +234,7 @@ func (t *binary[V]) _delete(n *binaryNode[V], key string) (*binaryNode[V], V, bo return n, val, ok } -// Min returns the minimum key and its value in the Binary Trie. +// Min returns the minimum key and its value in the binary trie. func (t *binary[V]) Min() (string, V, bool) { var key string var val V @@ -251,7 +251,7 @@ func (t *binary[V]) Min() (string, V, bool) { return key, val, ok } -// Max returns the maximum key and its value in the Binary Trie. +// Max returns the maximum key and its value in the binary trie. func (t *binary[V]) Max() (string, V, bool) { var key string var val V @@ -268,7 +268,7 @@ func (t *binary[V]) Max() (string, V, bool) { return key, val, ok } -// Floor returns the largest key in the Binary Trie less than or equal to key. +// Floor returns the largest key in the binary trie less than or equal to key. func (t *binary[V]) Floor(key string) (string, V, bool) { var lastKey string var lastVal V @@ -288,7 +288,7 @@ func (t *binary[V]) Floor(key string) (string, V, bool) { return lastKey, lastVal, ok } -// Ceiling returns the smallest key in the Binary Trie greater than or equal to key. +// Ceiling returns the smallest key in the binary trie greater than or equal to key. func (t *binary[V]) Ceiling(key string) (string, V, bool) { var lastKey string var lastVal V @@ -308,7 +308,7 @@ func (t *binary[V]) Ceiling(key string) (string, V, bool) { return lastKey, lastVal, ok } -// DeleteMin removes the smallest key and associated value from the Binary Trie. +// DeleteMin removes the smallest key and associated value from the binary trie. func (t *binary[V]) DeleteMin() (string, V, bool) { key, val, ok := t.Min() if !ok { @@ -322,7 +322,7 @@ func (t *binary[V]) DeleteMin() (string, V, bool) { return key, val, true } -// DeleteMax removes the largest key and associated value from the Binary Trie. +// DeleteMax removes the largest key and associated value from the binary trie. func (t *binary[V]) DeleteMax() (string, V, bool) { key, val, ok := t.Max() if !ok { @@ -336,7 +336,7 @@ func (t *binary[V]) DeleteMax() (string, V, bool) { return key, val, true } -// Select returns the k-th smallest key in the Binary Trie. +// Select returns the k-th smallest key in the binary trie. func (t *binary[V]) Select(rank int) (string, V, bool) { var lastKey string var lastVal V @@ -363,7 +363,7 @@ func (t *binary[V]) Select(rank int) (string, V, bool) { return lastKey, lastVal, ok } -// Rank returns the number of keys in the Binary Trie less than key. +// Rank returns the number of keys in the binary trie less than key. func (t *binary[V]) Rank(key string) int { i := 0 t._traverse(t.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { @@ -381,7 +381,7 @@ func (t *binary[V]) Rank(key string) int { return i } -// Range returns all keys and associated values in the Binary Trie between two given keys. +// Range returns all keys and associated values in the binary trie between two given keys. func (t *binary[V]) Range(lo, hi string) []KeyValue[string, V] { kvs := []KeyValue[string, V]{} t._traverse(t.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { @@ -399,7 +399,7 @@ func (t *binary[V]) Range(lo, hi string) []KeyValue[string, V] { return kvs } -// RangeSize returns the number of keys in the Binary Trie between two given keys. +// RangeSize returns the number of keys in the binary trie between two given keys. func (t *binary[V]) RangeSize(lo, hi string) int { i := 0 t._traverse(t.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { @@ -479,7 +479,7 @@ func (t *binary[V]) _withPrefix(n *binaryNode[V], prefix, key string, visit func } } -// LongestPrefix returns the key and associated value in Binary trie +// LongestPrefixOf returns the key and associated value in Binary trie // that is the longest prefix of the given key. func (t *binary[V]) LongestPrefixOf(key string) (string, V, bool) { var lastKey string @@ -509,7 +509,7 @@ func (t *binary[V]) _allPrefixOf(n *binaryNode[V], prefix, key string, visit fun } } -// String returns a string representation of the Binary trie. +// String returns a string representation of the binary trie. func (t *binary[V]) String() string { i := 0 pairs := make([]string, t.Size()) @@ -526,19 +526,19 @@ func (t *binary[V]) String() string { } // Equals determines whether or not two Binary Tries have the same key-value pairs. -func (t *binary[V]) Equals(u Trie[V]) bool { - tt, ok := u.(*binary[V]) +func (t *binary[V]) Equals(rhs Trie[V]) bool { + t2, ok := rhs.(*binary[V]) if !ok { return false } - return t._traverse(t.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { // t ⊂ tt + return t._traverse(t.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { // t ⊂ t2 if n.term { - val, ok := tt.Get(k) + val, ok := t2.Get(k) return ok && t.eqVal(n.val, val) } return true - }) && tt._traverse(tt.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { // tt ⊂ t + }) && t2._traverse(t2.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { // t2 ⊂ t if n.term { val, ok := t.Get(k) return ok && t.eqVal(n.val, val) @@ -547,7 +547,7 @@ func (t *binary[V]) Equals(u Trie[V]) bool { }) } -// All returns an iterator sequence containing all the key-value pairs in the Binary Trie. +// All returns an iterator sequence containing all the key-value pairs in the binary trie. func (t *binary[V]) All() iter.Seq2[string, V] { return func(yield func(string, V) bool) { t._traverse(t.root.left, "", Ascending, func(k string, n *binaryNode[V]) bool { @@ -556,22 +556,22 @@ func (t *binary[V]) All() iter.Seq2[string, V] { } } -// AnyMatch returns true if at least one key-value pair in the Binary Trie satisfies the provided predicate. +// AnyMatch returns true if at least one key-value pair in the binary trie satisfies the provided predicate. func (t *binary[V]) AnyMatch(p Predicate2[string, V]) bool { return !t._traverse(t.root.left, "", VLR, func(key string, n *binaryNode[V]) bool { - return !p(key, n.val) + return !n.term || !p(key, n.val) }) } -// AllMatch returns true if all key-value pairs in the Binary Trie satisfy the provided predicate. -// If the Binary Trie is empty, it returns true. +// AllMatch returns true if all key-value pairs in the binary trie satisfy the provided predicate. +// If the binary trie is empty, it returns true. func (t *binary[V]) AllMatch(p Predicate2[string, V]) bool { return t._traverse(t.root.left, "", VLR, func(key string, n *binaryNode[V]) bool { - return p(key, n.val) + return !n.term || p(key, n.val) }) } -// Traverse performs a traversal of the Binary Trie using the specified traversal order +// Traverse performs a traversal of the binary trie using the specified traversal order // and yields the key-value pair of each node to the provided VisitFunc2 function. // // If the function returns false, the traversal is halted. @@ -585,8 +585,8 @@ func (t *binary[V]) Traverse(order TraverseOrder, visit VisitFunc2[string, V]) { }) } -// AllMatch returns true if all key-value pairs in the Binary Trie satisfy the provided predicate. -// If the Binary Trie is empty, it returns false. +// AllMatch returns true if all key-value pairs in the binary trie satisfy the provided predicate. +// If the binary trie is empty, it returns false. func (t *binary[V]) _traverse(n *binaryNode[V], prefix string, order TraverseOrder, visit func(string, *binaryNode[V]) bool) bool { if n == nil { return true @@ -612,7 +612,7 @@ func (t *binary[V]) _traverse(n *binaryNode[V], prefix string, order TraverseOrd } } -// Graphviz generates and returns a string representation of the Binary Trie in DOT format. +// Graphviz generates and returns a string representation of the binary trie in DOT format. // This format is commonly used for visualizing graphs with Graphviz tools. func (t *binary[V]) Graphviz() string { // Create a map of node --> id diff --git a/trie/binary_test.go b/trie/binary_test.go index 01149ed..5ba5874 100644 --- a/trie/binary_test.go +++ b/trie/binary_test.go @@ -11,6 +11,8 @@ func getBinaryTests() []trieTest[int] { tests[0].trie = "Binary Trie" tests[0].expectedHeight = 3 + tests[0].equals = nil + tests[0].expectedEquals = false tests[0].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}} tests[0].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}} tests[0].expectedLVRTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}, {Key: "", Val: 0}} @@ -19,8 +21,6 @@ func getBinaryTests() []trieTest[int] { tests[0].expectedRLVTraverse = []KeyValue[string, int]{{Key: "C", Val: 3}, {Key: "B", Val: 2}, {Key: "A", Val: 1}, {Key: "", Val: 0}} tests[0].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}} tests[0].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "C", Val: 3}, {Key: "B", Val: 2}, {Key: "A", Val: 1}, {Key: "", Val: 0}} - tests[0].equals = nil - tests[0].expectedEquals = false tests[0].expectedGraphviz = `strict digraph "Binary Trie" { concentrate=false; node [shape=circle]; @@ -37,6 +37,8 @@ func getBinaryTests() []trieTest[int] { tests[1].trie = "Binary Trie" tests[1].expectedHeight = 5 + tests[1].equals = NewBinary[int](nil) + tests[1].expectedEquals = false tests[1].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}, {Key: "D", Val: 4}, {Key: "E", Val: 5}} tests[1].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}, {Key: "D", Val: 4}, {Key: "E", Val: 5}} tests[1].expectedLVRTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}, {Key: "D", Val: 4}, {Key: "E", Val: 5}, {Key: "", Val: 0}} @@ -45,8 +47,6 @@ func getBinaryTests() []trieTest[int] { tests[1].expectedRLVTraverse = []KeyValue[string, int]{{Key: "E", Val: 5}, {Key: "D", Val: 4}, {Key: "C", Val: 3}, {Key: "B", Val: 2}, {Key: "A", Val: 1}, {Key: "", Val: 0}} tests[1].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}, {Key: "D", Val: 4}, {Key: "E", Val: 5}} tests[1].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "E", Val: 5}, {Key: "D", Val: 4}, {Key: "C", Val: 3}, {Key: "B", Val: 2}, {Key: "A", Val: 1}, {Key: "", Val: 0}} - tests[1].equals = NewBinary[int](nil) - tests[1].expectedEquals = false tests[1].expectedGraphviz = `strict digraph "Binary Trie" { concentrate=false; node [shape=circle]; @@ -67,6 +67,11 @@ func getBinaryTests() []trieTest[int] { tests[2].trie = "Binary Trie" tests[2].expectedHeight = 7 + tests[2].equals = NewBinary[int](nil) + tests[2].equals.Put("A", 1) + tests[2].equals.Put("D", 4) + tests[2].equals.Put("G", 7) + tests[2].expectedEquals = false tests[2].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "D", Val: 4}, {Key: "G", Val: 7}, {Key: "J", Val: 10}, {Key: "M", Val: 13}, {Key: "P", Val: 16}, {Key: "S", Val: 19}} tests[2].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "D", Val: 4}, {Key: "G", Val: 7}, {Key: "J", Val: 10}, {Key: "M", Val: 13}, {Key: "P", Val: 16}, {Key: "S", Val: 19}} tests[2].expectedLVRTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "D", Val: 4}, {Key: "G", Val: 7}, {Key: "J", Val: 10}, {Key: "M", Val: 13}, {Key: "P", Val: 16}, {Key: "S", Val: 19}, {Key: "", Val: 0}} @@ -75,11 +80,6 @@ func getBinaryTests() []trieTest[int] { tests[2].expectedRLVTraverse = []KeyValue[string, int]{{Key: "S", Val: 19}, {Key: "P", Val: 16}, {Key: "M", Val: 13}, {Key: "J", Val: 10}, {Key: "G", Val: 7}, {Key: "D", Val: 4}, {Key: "A", Val: 1}, {Key: "", Val: 0}} tests[2].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "A", Val: 1}, {Key: "D", Val: 4}, {Key: "G", Val: 7}, {Key: "J", Val: 10}, {Key: "M", Val: 13}, {Key: "P", Val: 16}, {Key: "S", Val: 19}} tests[2].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "S", Val: 19}, {Key: "P", Val: 16}, {Key: "M", Val: 13}, {Key: "J", Val: 10}, {Key: "G", Val: 7}, {Key: "D", Val: 4}, {Key: "A", Val: 1}, {Key: "", Val: 0}} - tests[2].equals = NewBinary[int](nil) - tests[2].equals.Put("A", 1) - tests[2].equals.Put("D", 4) - tests[2].equals.Put("G", 7) - tests[2].expectedEquals = false tests[2].expectedGraphviz = `strict digraph "Binary Trie" { concentrate=false; node [shape=circle]; @@ -104,14 +104,6 @@ func getBinaryTests() []trieTest[int] { tests[3].trie = "Binary Trie" tests[3].expectedHeight = 8 - tests[3].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "y", Val: 5}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "d", Val: 0}, {Key: "a", Val: 0}, {Key: "d", Val: 3}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}} - tests[3].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "b", Val: 0}, {Key: "d", Val: 0}, {Key: "a", Val: 0}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}, {Key: "d", Val: 3}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "a", Val: 0}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "b", Val: 0}, {Key: "l", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "y", Val: 5}} - tests[3].expectedLVRTraverse = []KeyValue[string, int]{{Key: "y", Val: 5}, {Key: "b", Val: 0}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "a", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "b", Val: 0}, {Key: "d", Val: 3}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "a", Val: 0}, {Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "d", Val: 0}, {Key: "", Val: 0}} - tests[3].expectedRVLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "d", Val: 0}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}, {Key: "a", Val: 0}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "d", Val: 3}, {Key: "b", Val: 0}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "a", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "b", Val: 0}, {Key: "y", Val: 5}} - tests[3].expectedLRVTraverse = []KeyValue[string, int]{{Key: "y", Val: 5}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "l", Val: 0}, {Key: "b", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "a", Val: 0}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 3}, {Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "a", Val: 0}, {Key: "d", Val: 0}, {Key: "b", Val: 0}, {Key: "", Val: 0}} - tests[3].expectedRLVTraverse = []KeyValue[string, int]{{Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 3}, {Key: "a", Val: 0}, {Key: "d", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "y", Val: 5}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "", Val: 0}} - tests[3].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "y", Val: 5}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "d", Val: 0}, {Key: "a", Val: 0}, {Key: "d", Val: 3}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}} - tests[3].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 3}, {Key: "a", Val: 0}, {Key: "d", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "y", Val: 5}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "", Val: 0}} tests[3].equals = NewBinary[int](nil) tests[3].equals.Put("box", 2) tests[3].equals.Put("dad", 3) @@ -121,6 +113,14 @@ func getBinaryTests() []trieTest[int] { tests[3].equals.Put("dance", 13) tests[3].equals.Put("balloon", 17) tests[3].expectedEquals = true + tests[3].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "y", Val: 5}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "d", Val: 0}, {Key: "a", Val: 0}, {Key: "d", Val: 3}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}} + tests[3].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "b", Val: 0}, {Key: "d", Val: 0}, {Key: "a", Val: 0}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}, {Key: "d", Val: 3}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "a", Val: 0}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "b", Val: 0}, {Key: "l", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "y", Val: 5}} + tests[3].expectedLVRTraverse = []KeyValue[string, int]{{Key: "y", Val: 5}, {Key: "b", Val: 0}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "a", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "b", Val: 0}, {Key: "d", Val: 3}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "a", Val: 0}, {Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "d", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedRVLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "d", Val: 0}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}, {Key: "a", Val: 0}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "d", Val: 3}, {Key: "b", Val: 0}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "a", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "b", Val: 0}, {Key: "y", Val: 5}} + tests[3].expectedLRVTraverse = []KeyValue[string, int]{{Key: "y", Val: 5}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "l", Val: 0}, {Key: "b", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "a", Val: 0}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 3}, {Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "a", Val: 0}, {Key: "d", Val: 0}, {Key: "b", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedRLVTraverse = []KeyValue[string, int]{{Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 3}, {Key: "a", Val: 0}, {Key: "d", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "y", Val: 5}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "y", Val: 5}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "n", Val: 17}, {Key: "n", Val: 0}, {Key: "d", Val: 11}, {Key: "o", Val: 0}, {Key: "x", Val: 2}, {Key: "d", Val: 0}, {Key: "a", Val: 0}, {Key: "d", Val: 3}, {Key: "n", Val: 0}, {Key: "c", Val: 0}, {Key: "e", Val: 13}, {Key: "o", Val: 0}, {Key: "m", Val: 0}, {Key: "e", Val: 7}} + tests[3].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "e", Val: 7}, {Key: "m", Val: 0}, {Key: "o", Val: 0}, {Key: "e", Val: 13}, {Key: "c", Val: 0}, {Key: "n", Val: 0}, {Key: "d", Val: 3}, {Key: "a", Val: 0}, {Key: "d", Val: 0}, {Key: "x", Val: 2}, {Key: "o", Val: 0}, {Key: "d", Val: 11}, {Key: "n", Val: 0}, {Key: "n", Val: 17}, {Key: "o", Val: 0}, {Key: "o", Val: 0}, {Key: "l", Val: 0}, {Key: "l", Val: 0}, {Key: "y", Val: 5}, {Key: "b", Val: 0}, {Key: "a", Val: 0}, {Key: "b", Val: 0}, {Key: "", Val: 0}} tests[3].expectedGraphviz = `strict digraph "Binary Trie" { concentrate=false; node [shape=circle]; diff --git a/trie/patricia.go b/trie/patricia.go index 845e864..6847679 100644 --- a/trie/patricia.go +++ b/trie/patricia.go @@ -239,12 +239,12 @@ func (t *patricia[V]) remove(n, r, rp, np *patriciaNode[V]) { } } -// Size returns the number of key-value pairs in the Patricia Trie. +// Size returns the number of key-value pairs in the Patricia trie. func (t *patricia[V]) Size() int { return t.size } -// Height returns the height of the Patricia Trie. +// Height returns the height of the Patricia trie. func (t *patricia[V]) Height() int { if t.root == nil { return 0 @@ -261,12 +261,12 @@ func (t *patricia[V]) _height(prev, curr *patriciaNode[V]) int { return 1 + Max[int](t._height(curr, curr.left), t._height(curr, curr.right)) } -// IsEmpty returns true if the Patricia Trie is empty. +// IsEmpty returns true if the Patricia trie is empty. func (t *patricia[V]) IsEmpty() bool { return t.size == 0 } -// Put adds a new key-value pair to the Patricia Trie. +// Put adds a new key-value pair to the Patricia trie. func (t *patricia[V]) Put(key string, val V) { t._put(newBitString(key), val) } @@ -321,7 +321,7 @@ func (t *patricia[V]) _put(key *bitString, val V) { t.size++ } -// Get returns the value of a given key in the Patricia Trie. +// Get returns the value of a given key in the Patricia trie. func (t *patricia[V]) Get(key string) (V, bool) { return t._get(newBitString(key)) } @@ -335,7 +335,7 @@ func (t *patricia[V]) _get(key *bitString) (V, bool) { return zeroV, false } -// Delete removes a key-value pair from the Patricia Trie. +// Delete removes a key-value pair from the Patricia trie. func (t *patricia[V]) Delete(key string) (V, bool) { return t._delete(newBitString(key)) } @@ -378,7 +378,7 @@ func (t *patricia[V]) _delete(key *bitString) (V, bool) { return n.val, true } -// Min returns the minimum key and its value in the Patricia Trie. +// Min returns the minimum key and its value in the Patricia trie. func (t *patricia[V]) Min() (string, V, bool) { return t._min(t.root) } @@ -396,7 +396,7 @@ func (t *patricia[V]) _min(n *patriciaNode[V]) (string, V, bool) { return t._min(n.left) } -// Max returns the maximum key and its value in the Patricia Trie. +// Max returns the maximum key and its value in the Patricia trie. func (t *patricia[V]) Max() (string, V, bool) { return t._max(t.root) } @@ -421,7 +421,7 @@ func (t *patricia[V]) _max(n *patriciaNode[V]) (string, V, bool) { return t._max(next) } -// Floor returns the largest key in the Patricia Trie less than or equal to key. +// Floor returns the largest key in the Patricia trie less than or equal to key. func (t *patricia[V]) Floor(key string) (string, V, bool) { var lastKey string var lastVal V @@ -438,7 +438,7 @@ func (t *patricia[V]) Floor(key string) (string, V, bool) { return lastKey, lastVal, ok } -// Ceiling returns the smallest key in the Patricia Trie greater than or equal to key. +// Ceiling returns the smallest key in the Patricia trie greater than or equal to key. func (t *patricia[V]) Ceiling(key string) (string, V, bool) { var lastKey string var lastVal V @@ -455,7 +455,7 @@ func (t *patricia[V]) Ceiling(key string) (string, V, bool) { return lastKey, lastVal, ok } -// DeleteMin removes the smallest key and associated value from the Patricia Trie. +// DeleteMin removes the smallest key and associated value from the Patricia trie. func (t *patricia[V]) DeleteMin() (string, V, bool) { if t.root == nil { var zeroV V @@ -479,7 +479,7 @@ func (t *patricia[V]) DeleteMin() (string, V, bool) { return n.key.String(), n.val, true } -// DeleteMax removes the largest key and associated value from the Patricia Trie. +// DeleteMax removes the largest key and associated value from the Patricia trie. func (t *patricia[V]) DeleteMax() (string, V, bool) { if t.root == nil { var zeroV V @@ -503,7 +503,7 @@ func (t *patricia[V]) DeleteMax() (string, V, bool) { return n.key.String(), n.val, true } -// Select returns the k-th smallest key in the Patricia Trie. +// Select returns the k-th smallest key in the Patricia trie. func (t *patricia[V]) Select(rank int) (string, V, bool) { var lastKey string var lastVal V @@ -527,7 +527,7 @@ func (t *patricia[V]) Select(rank int) (string, V, bool) { return lastKey, lastVal, ok } -// Rank returns the number of keys in the Patricia Trie less than key. +// Rank returns the number of keys in the Patricia trie less than key. func (t *patricia[V]) Rank(key string) int { i := 0 @@ -545,7 +545,7 @@ func (t *patricia[V]) Rank(key string) int { return i } -// Range returns all keys and associated values in the Patricia Trie between two given keys. +// Range returns all keys and associated values in the Patricia trie between two given keys. func (t *patricia[V]) Range(lo, hi string) []KeyValue[string, V] { kvs := []KeyValue[string, V]{} @@ -564,7 +564,7 @@ func (t *patricia[V]) Range(lo, hi string) []KeyValue[string, V] { return kvs } -// RangeSize returns the number of keys in the Patricia Trie between two given keys. +// RangeSize returns the number of keys in the Patricia trie between two given keys. func (t *patricia[V]) RangeSize(lo, hi string) int { i := 0 @@ -583,7 +583,7 @@ func (t *patricia[V]) RangeSize(lo, hi string) int { return i } -// Match returns all the keys and associated values in the Patricia Trie +// Match returns all the keys and associated values in the Patricia trie // that match the given pattern in which * matches any character. func (t *patricia[V]) Match(pattern string) []KeyValue[string, V] { kvs := []KeyValue[string, V]{} @@ -613,7 +613,7 @@ func (t *patricia[V]) _match(prev, curr *patriciaNode[V], pattern *bitPattern, v } } -// WithPrefix returns all the keys and associated values in the Patricia Trie with the given prefix. +// WithPrefix returns all the keys and associated values in the Patricia trie with the given prefix. func (t *patricia[V]) WithPrefix(key string) []KeyValue[string, V] { kvs := []KeyValue[string, V]{} bitKey := newBitString(key) @@ -630,7 +630,7 @@ func (t *patricia[V]) WithPrefix(key string) []KeyValue[string, V] { return kvs } -// LongestPrefix returns the key and associated value in the Patricia Trie +// LongestPrefixOf returns the key and associated value in the Patricia trie // that is the longest prefix of the given key. func (t *patricia[V]) LongestPrefixOf(key string) (string, V, bool) { bitKey := newBitString(key) @@ -657,22 +657,22 @@ func (t *patricia[V]) String() string { } // Equals determines whether or not two Patricia Tries have the same key-value pairs. -func (t *patricia[V]) Equals(u Trie[V]) bool { - tt, ok := u.(*patricia[V]) +func (t *patricia[V]) Equals(rhs Trie[V]) bool { + t2, ok := rhs.(*patricia[V]) if !ok { return false } - return t._traverse(t.root, Ascending, func(n *patriciaNode[V]) bool { // t ⊂ tt - val, ok := tt._get(n.key) + return t._traverse(t.root, Ascending, func(n *patriciaNode[V]) bool { // t ⊂ t2 + val, ok := t2._get(n.key) return ok && t.eqVal(n.val, val) - }) && tt._traverse(tt.root, Ascending, func(n *patriciaNode[V]) bool { // tt ⊂ t + }) && t2._traverse(t2.root, Ascending, func(n *patriciaNode[V]) bool { // t2 ⊂ t val, ok := t._get(n.key) return ok && t.eqVal(n.val, val) }) } -// All returns an iterator sequence containing all the key-value pairs in the Patricia Trie. +// All returns an iterator sequence containing all the key-value pairs in the Patricia trie. func (t *patricia[V]) All() iter.Seq2[string, V] { return func(yield func(string, V) bool) { t._traverse(t.root, Ascending, func(n *patriciaNode[V]) bool { @@ -681,22 +681,22 @@ func (t *patricia[V]) All() iter.Seq2[string, V] { } } -// AnyMatch returns true if at least one key-value pair in the Patricia Trie satisfies the provided predicate. +// AnyMatch returns true if at least one key-value pair in the Patricia trie satisfies the provided predicate. func (t *patricia[V]) AnyMatch(p Predicate2[string, V]) bool { return !t._traverse(t.root, VLR, func(n *patriciaNode[V]) bool { return !p(n.key.String(), n.val) }) } -// AllMatch returns true if all key-value pairs in the Patricia Trie satisfy the provided predicate. -// If the Patricia Trie is empty, it returns true. +// AllMatch returns true if all key-value pairs in the Patricia trie satisfy the provided predicate. +// If the Patricia trie is empty, it returns true. func (t *patricia[V]) AllMatch(p Predicate2[string, V]) bool { return t._traverse(t.root, VLR, func(n *patriciaNode[V]) bool { return p(n.key.String(), n.val) }) } -// Traverse performs a traversal of the Patricia Trie using the specified traversal order +// Traverse performs a traversal of the Patricia trie using the specified traversal order // and yields the key-value pair of each node to the provided VisitFunc2 function. // // If the function returns false, the traversal is halted. @@ -706,8 +706,8 @@ func (t *patricia[V]) Traverse(order TraverseOrder, visit VisitFunc2[string, V]) }) } -// AllMatch returns true if all key-value pairs in the Patricia Trie satisfy the provided predicate. -// If the Patricia Trie is empty, it returns false. +// AllMatch returns true if all key-value pairs in the Patricia trie satisfy the provided predicate. +// If the Patricia trie is empty, it returns false. func (t *patricia[V]) _traverse(n *patriciaNode[V], order TraverseOrder, visit func(*patriciaNode[V]) bool) bool { if n == nil { return true @@ -764,7 +764,7 @@ func (t *patricia[V]) _traverse(n *patriciaNode[V], order TraverseOrder, visit f } } -// Graphviz generates and returns a string representation of the Patricia Trie in DOT format. +// Graphviz generates and returns a string representation of the Patricia trie in DOT format. // This format is commonly used for visualizing graphs with Graphviz tools. func (t *patricia[V]) Graphviz() string { // Create a map of node --> id diff --git a/trie/patricia_test.go b/trie/patricia_test.go index a031e10..da49df1 100644 --- a/trie/patricia_test.go +++ b/trie/patricia_test.go @@ -11,6 +11,8 @@ func getPatriciaTests() []trieTest[int] { tests[0].trie = "Patricia" tests[0].expectedHeight = 2 + tests[0].equals = nil + tests[0].expectedEquals = false tests[0].expectedVLRTraverse = []KeyValue[string, int]{{Key: "B", Val: 2}, {Key: "A", Val: 1}, {Key: "C", Val: 3}} tests[0].expectedVRLTraverse = []KeyValue[string, int]{{Key: "B", Val: 2}, {Key: "A", Val: 1}, {Key: "C", Val: 3}} tests[0].expectedLVRTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "C", Val: 3}, {Key: "B", Val: 2}} @@ -19,8 +21,6 @@ func getPatriciaTests() []trieTest[int] { tests[0].expectedRLVTraverse = []KeyValue[string, int]{{Key: "C", Val: 3}, {Key: "A", Val: 1}, {Key: "B", Val: 2}} tests[0].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}} tests[0].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "C", Val: 3}, {Key: "B", Val: 2}, {Key: "A", Val: 1}} - tests[0].equals = nil - tests[0].expectedEquals = false tests[0].expectedGraphviz = `strict digraph "Patricia" { rankdir=TB; concentrate=false; @@ -39,6 +39,8 @@ func getPatriciaTests() []trieTest[int] { tests[1].trie = "Patricia" tests[1].expectedHeight = 3 + tests[1].equals = NewPatricia[int](nil) + tests[1].expectedEquals = false tests[1].expectedVLRTraverse = []KeyValue[string, int]{{Key: "B", Val: 2}, {Key: "D", Val: 4}, {Key: "A", Val: 1}, {Key: "C", Val: 3}, {Key: "E", Val: 5}} tests[1].expectedVRLTraverse = []KeyValue[string, int]{{Key: "B", Val: 2}, {Key: "D", Val: 4}, {Key: "E", Val: 5}, {Key: "A", Val: 1}, {Key: "C", Val: 3}} tests[1].expectedLVRTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "C", Val: 3}, {Key: "D", Val: 4}, {Key: "E", Val: 5}, {Key: "B", Val: 2}} @@ -47,8 +49,6 @@ func getPatriciaTests() []trieTest[int] { tests[1].expectedRLVTraverse = []KeyValue[string, int]{{Key: "E", Val: 5}, {Key: "C", Val: 3}, {Key: "A", Val: 1}, {Key: "D", Val: 4}, {Key: "B", Val: 2}} tests[1].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "B", Val: 2}, {Key: "C", Val: 3}, {Key: "D", Val: 4}, {Key: "E", Val: 5}} tests[1].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "E", Val: 5}, {Key: "D", Val: 4}, {Key: "C", Val: 3}, {Key: "B", Val: 2}, {Key: "A", Val: 1}} - tests[1].equals = NewPatricia[int](nil) - tests[1].expectedEquals = false tests[1].expectedGraphviz = `strict digraph "Patricia" { rankdir=TB; concentrate=false; @@ -73,6 +73,11 @@ func getPatriciaTests() []trieTest[int] { tests[2].trie = "Patricia" tests[2].expectedHeight = 4 + tests[2].equals = NewPatricia[int](nil) + tests[2].equals.Put("A", 1) + tests[2].equals.Put("D", 4) + tests[2].equals.Put("G", 7) + tests[2].expectedEquals = false tests[2].expectedVLRTraverse = []KeyValue[string, int]{{Key: "J", Val: 10}, {Key: "P", Val: 16}, {Key: "D", Val: 4}, {Key: "A", Val: 1}, {Key: "G", Val: 7}, {Key: "M", Val: 13}, {Key: "S", Val: 19}} tests[2].expectedVRLTraverse = []KeyValue[string, int]{{Key: "J", Val: 10}, {Key: "P", Val: 16}, {Key: "S", Val: 19}, {Key: "D", Val: 4}, {Key: "M", Val: 13}, {Key: "A", Val: 1}, {Key: "G", Val: 7}} tests[2].expectedLVRTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "G", Val: 7}, {Key: "D", Val: 4}, {Key: "M", Val: 13}, {Key: "P", Val: 16}, {Key: "S", Val: 19}, {Key: "J", Val: 10}} @@ -81,11 +86,6 @@ func getPatriciaTests() []trieTest[int] { tests[2].expectedRLVTraverse = []KeyValue[string, int]{{Key: "S", Val: 19}, {Key: "M", Val: 13}, {Key: "G", Val: 7}, {Key: "A", Val: 1}, {Key: "D", Val: 4}, {Key: "P", Val: 16}, {Key: "J", Val: 10}} tests[2].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "A", Val: 1}, {Key: "D", Val: 4}, {Key: "G", Val: 7}, {Key: "J", Val: 10}, {Key: "M", Val: 13}, {Key: "P", Val: 16}, {Key: "S", Val: 19}} tests[2].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "S", Val: 19}, {Key: "P", Val: 16}, {Key: "M", Val: 13}, {Key: "J", Val: 10}, {Key: "G", Val: 7}, {Key: "D", Val: 4}, {Key: "A", Val: 1}} - tests[2].equals = NewPatricia[int](nil) - tests[2].equals.Put("A", 1) - tests[2].equals.Put("D", 4) - tests[2].equals.Put("G", 7) - tests[2].expectedEquals = false tests[2].expectedGraphviz = `strict digraph "Patricia" { rankdir=TB; concentrate=false; @@ -116,14 +116,6 @@ func getPatriciaTests() []trieTest[int] { tests[3].trie = "Patricia" tests[3].expectedHeight = 4 - tests[3].expectedVLRTraverse = []KeyValue[string, int]{{Key: "box", Val: 2}, {Key: "dad", Val: 3}, {Key: "band", Val: 11}, {Key: "baby", Val: 5}, {Key: "balloon", Val: 17}, {Key: "dome", Val: 7}, {Key: "dance", Val: 13}} - tests[3].expectedVRLTraverse = []KeyValue[string, int]{{Key: "box", Val: 2}, {Key: "dad", Val: 3}, {Key: "dome", Val: 7}, {Key: "dance", Val: 13}, {Key: "band", Val: 11}, {Key: "baby", Val: 5}, {Key: "balloon", Val: 17}} - tests[3].expectedLVRTraverse = []KeyValue[string, int]{{Key: "baby", Val: 5}, {Key: "balloon", Val: 17}, {Key: "band", Val: 11}, {Key: "dad", Val: 3}, {Key: "dance", Val: 13}, {Key: "dome", Val: 7}, {Key: "box", Val: 2}} - tests[3].expectedRVLTraverse = []KeyValue[string, int]{{Key: "box", Val: 2}, {Key: "dome", Val: 7}, {Key: "dance", Val: 13}, {Key: "dad", Val: 3}, {Key: "band", Val: 11}, {Key: "balloon", Val: 17}, {Key: "baby", Val: 5}} - tests[3].expectedLRVTraverse = []KeyValue[string, int]{{Key: "balloon", Val: 17}, {Key: "baby", Val: 5}, {Key: "band", Val: 11}, {Key: "dance", Val: 13}, {Key: "dome", Val: 7}, {Key: "dad", Val: 3}, {Key: "box", Val: 2}} - tests[3].expectedRLVTraverse = []KeyValue[string, int]{{Key: "dance", Val: 13}, {Key: "dome", Val: 7}, {Key: "balloon", Val: 17}, {Key: "baby", Val: 5}, {Key: "band", Val: 11}, {Key: "dad", Val: 3}, {Key: "box", Val: 2}} - tests[3].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "baby", Val: 5}, {Key: "balloon", Val: 17}, {Key: "band", Val: 11}, {Key: "box", Val: 2}, {Key: "dad", Val: 3}, {Key: "dance", Val: 13}, {Key: "dome", Val: 7}} - tests[3].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "dome", Val: 7}, {Key: "dance", Val: 13}, {Key: "dad", Val: 3}, {Key: "box", Val: 2}, {Key: "band", Val: 11}, {Key: "balloon", Val: 17}, {Key: "baby", Val: 5}} tests[3].equals = NewPatricia[int](nil) tests[3].equals.Put("box", 2) tests[3].equals.Put("dad", 3) @@ -133,6 +125,14 @@ func getPatriciaTests() []trieTest[int] { tests[3].equals.Put("dance", 13) tests[3].equals.Put("balloon", 17) tests[3].expectedEquals = true + tests[3].expectedVLRTraverse = []KeyValue[string, int]{{Key: "box", Val: 2}, {Key: "dad", Val: 3}, {Key: "band", Val: 11}, {Key: "baby", Val: 5}, {Key: "balloon", Val: 17}, {Key: "dome", Val: 7}, {Key: "dance", Val: 13}} + tests[3].expectedVRLTraverse = []KeyValue[string, int]{{Key: "box", Val: 2}, {Key: "dad", Val: 3}, {Key: "dome", Val: 7}, {Key: "dance", Val: 13}, {Key: "band", Val: 11}, {Key: "baby", Val: 5}, {Key: "balloon", Val: 17}} + tests[3].expectedLVRTraverse = []KeyValue[string, int]{{Key: "baby", Val: 5}, {Key: "balloon", Val: 17}, {Key: "band", Val: 11}, {Key: "dad", Val: 3}, {Key: "dance", Val: 13}, {Key: "dome", Val: 7}, {Key: "box", Val: 2}} + tests[3].expectedRVLTraverse = []KeyValue[string, int]{{Key: "box", Val: 2}, {Key: "dome", Val: 7}, {Key: "dance", Val: 13}, {Key: "dad", Val: 3}, {Key: "band", Val: 11}, {Key: "balloon", Val: 17}, {Key: "baby", Val: 5}} + tests[3].expectedLRVTraverse = []KeyValue[string, int]{{Key: "balloon", Val: 17}, {Key: "baby", Val: 5}, {Key: "band", Val: 11}, {Key: "dance", Val: 13}, {Key: "dome", Val: 7}, {Key: "dad", Val: 3}, {Key: "box", Val: 2}} + tests[3].expectedRLVTraverse = []KeyValue[string, int]{{Key: "dance", Val: 13}, {Key: "dome", Val: 7}, {Key: "balloon", Val: 17}, {Key: "baby", Val: 5}, {Key: "band", Val: 11}, {Key: "dad", Val: 3}, {Key: "box", Val: 2}} + tests[3].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "baby", Val: 5}, {Key: "balloon", Val: 17}, {Key: "band", Val: 11}, {Key: "box", Val: 2}, {Key: "dad", Val: 3}, {Key: "dance", Val: 13}, {Key: "dome", Val: 7}} + tests[3].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "dome", Val: 7}, {Key: "dance", Val: 13}, {Key: "dad", Val: 3}, {Key: "box", Val: 2}, {Key: "band", Val: 11}, {Key: "balloon", Val: 17}, {Key: "baby", Val: 5}} tests[3].expectedGraphviz = `strict digraph "Patricia" { rankdir=TB; concentrate=false; diff --git a/trie/radix.go b/trie/radix.go new file mode 100644 index 0000000..211a526 --- /dev/null +++ b/trie/radix.go @@ -0,0 +1,418 @@ +package trie + +import ( + "fmt" + "iter" + "strings" + + . "github.com/moorara/algo/generic" + "github.com/moorara/algo/internal/graphviz" +) + +type radixNode[V any] struct { + label []byte + val V + term bool + children []*radixNode[V] +} + +// search looks for a child node that is a prefix of the given key. +func (n *radixNode[V]) search(key []byte) (int, int) { + for i, e := range n.children { + // Children (edges) are sorted + if key[0] < e.label[0] { + return i, 0 + } + + j := 0 + for j < len(key) && j < len(e.label) && key[j] == e.label[j] { + j++ + } + + if j > 0 { + return i, j + } + } + + return len(n.children), 0 +} + +type radix[V any] struct { + size int + root *radixNode[V] + eqVal EqualFunc[V] +} + +// NewRadix creates a new Radix tree. +// +// A Radix tree is an ordered tree that represents a space-optimized trie (prefix tree). +// It is derived from a regular trie by merging each node, that is the only child of its parent, with its parent. +// +// Like regular tries, +// +// - The root node is always associated with the empty string. +// - Keys are stored on a path from the root node to any arbitrary node (keys are stored on edges). +// - All the descendants of a node have the same common prefix of the string associated with that node. +// +// Unlike regular tries, edges can be labeled with sequences of digits as well as single digits. +func NewRadix[V any](eqVal EqualFunc[V]) Trie[V] { + return &radix[V]{ + size: 0, + root: new(radixNode[V]), + eqVal: eqVal, + } +} + +func (t *radix[V]) verify() bool { + // TODO: + return false +} + +// Size returns the number of key-value pairs in the Radix tree. +func (t *radix[V]) Size() int { + return t.size +} + +// Height returns the height of the Radix tree. +func (t *radix[V]) Height() int { + return t._height(t.root) +} + +func (t *radix[V]) _height(n *radixNode[V]) int { + if n == nil { + return 0 + } + + h := 0 + for _, c := range n.children { + h = Max[int](h, t._height(c)) + } + + return 1 + h +} + +// IsEmpty returns true if the Radix tree is empty. +func (t *radix[V]) IsEmpty() bool { + return t.size == 0 +} + +// Put adds a new key-value pair to the Radix tree. +func (t *radix[V]) Put(key string, val V) { + k := []byte(key) + last := t.root + + for l := 0; l < len(k); { + i, j := last.search(k[l:]) + if j < len(last.children[i].label) { + break + } + + last = last.children[i] + l += len(last.label) + } + + if last.term { + last.val = val // Update value for the existing key + return + } + + // TODO: +} + +// Get returns the value of a given key in the Radix tree. +func (t *radix[V]) Get(key string) (V, bool) { + var zeroV V + + k := []byte(key) + curr := t.root + + for l := 0; l < len(k); { + i, j := curr.search(k[l:]) + if j < len(curr.children[i].label) { + return zeroV, false + } + + curr = curr.children[i] + l += len(curr.label) + } + + if curr.term { + return curr.val, true + } + + return zeroV, false +} + +// Delete removes a key-value pair from the Radix tree. +func (t *radix[V]) Delete(key string) (val V, ok bool) { + // TODO: + var zeroV V + return zeroV, false +} + +// Min returns the minimum key and its value in the Radix tree. +func (t *radix[V]) Min() (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// Max returns the maximum key and its value in the Radix tree. +func (t *radix[V]) Max() (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// Floor returns the largest key in the Radix tree less than or equal to key. +func (t *radix[V]) Floor(key string) (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// Ceiling returns the smallest key in the Radix tree greater than or equal to key. +func (t *radix[V]) Ceiling(key string) (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// DeleteMin removes the smallest key and associated value from the Radix tree. +func (t *radix[V]) DeleteMin() (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// DeleteMax removes the largest key and associated value from the Radix tree. +func (t *radix[V]) DeleteMax() (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// Select returns the k-th smallest key in the Radix tree. +func (t *radix[V]) Select(rank int) (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// Rank returns the number of keys in the Radix tree less than key. +func (t *radix[V]) Rank(key string) int { + // TODO: + return -1 +} + +// Range returns all keys and associated values in the Radix tree between two given keys. +func (t *radix[V]) Range(lo, hi string) []KeyValue[string, V] { + // TODO: + return nil +} + +// RangeSize returns the number of keys in the Radix tree between two given keys. +func (t *radix[V]) RangeSize(lo, hi string) int { + // TODO: + return -1 +} + +// Match returns all the keys and associated values in the radix trie +// that match the given pattern in which * matches any character. +func (t *radix[V]) Match(pattern string) []KeyValue[string, V] { + // TODO: + return nil +} + +// WithPrefix returns all the keys and associated values in the Radix tree having s as a prefix. +func (t *radix[V]) WithPrefix(prefix string) []KeyValue[string, V] { + // TODO: + return nil +} + +// LongestPrefixOf returns the key and associated value in the radix trie +// that is the longest prefix of the given key. +func (t *radix[V]) LongestPrefixOf(prefix string) (string, V, bool) { + // TODO: + var zeroV V + return "", zeroV, false +} + +// String returns a string representation of the radix trie. +func (t *radix[V]) String() string { + i := 0 + pairs := make([]string, t.Size()) + + t._traverse(t.root, "", Ascending, func(k string, n *radixNode[V]) bool { + if n.term { + pairs[i] = fmt.Sprintf("<%v:%v>", k, n.val) + i++ + } + return true + }) + + return fmt.Sprintf("{%s}", strings.Join(pairs, " ")) +} + +// Equals determines whether or not two radix tries have the same key-value pairs. +func (t *radix[V]) Equals(rhs Trie[V]) bool { + t2, ok := rhs.(*radix[V]) + if !ok { + return false + } + + return t._traverse(t.root, "", Ascending, func(k string, n *radixNode[V]) bool { // t ⊂ t2 + if n.term { + val, ok := t2.Get(k) + return ok && t.eqVal(n.val, val) + } + return true + }) && t2._traverse(t2.root, "", Ascending, func(k string, n *radixNode[V]) bool { // t2 ⊂ t + if n.term { + val, ok := t.Get(k) + return ok && t.eqVal(n.val, val) + } + return true + }) +} + +// All returns an iterator sequence containing all the key-value pairs in the radix trie. +func (t *radix[V]) All() iter.Seq2[string, V] { + return func(yield func(string, V) bool) { + t._traverse(t.root, "", Ascending, func(k string, n *radixNode[V]) bool { + return !n.term || yield(k, n.val) + }) + } +} + +// AnyMatch returns true if at least one key-value pair in the radix trie satisfies the provided predicate. +func (t *radix[V]) AnyMatch(p Predicate2[string, V]) bool { + return !t._traverse(t.root, "", VLR, func(key string, n *radixNode[V]) bool { + return !n.term || !p(key, n.val) + }) +} + +// AllMatch returns true if all key-value pairs in the radix trie satisfy the provided predicate. +// If the radix trie is empty, it returns true. +func (t *radix[V]) AllMatch(p Predicate2[string, V]) bool { + return t._traverse(t.root, "", VLR, func(key string, n *radixNode[V]) bool { + return !n.term || p(key, n.val) + }) +} + +// Traverse performs a traversal of the radix trie using the specified traversal order +// and yields the key-value pair of each node to the provided VisitFunc2 function. +// +// If the function returns false, the traversal is halted. +func (t *radix[V]) Traverse(order TraverseOrder, visit VisitFunc2[string, V]) { + t._traverse(t.root, "", order, func(_ string, n *radixNode[V]) bool { + return visit(string(n.label), n.val) + }) +} + +func (t *radix[V]) _traverse(n *radixNode[V], prefix string, order TraverseOrder, visit func(string, *radixNode[V]) bool) bool { + if n == nil { + return true + } + + prefix = prefix + string(n.label) + + switch order { + case VLR, Ascending: + res := visit(prefix, n) + for i := 0; i < len(n.children); i++ { + res = res && t._traverse(n.children[i], prefix, order, visit) + } + return res + + case VRL: + res := visit(prefix, n) + for i := len(n.children) - 1; i >= 0; i-- { + res = res && t._traverse(n.children[i], prefix, order, visit) + } + return res + + case LRV: + res := true + for i := 0; i < len(n.children); i++ { + res = res && t._traverse(n.children[i], prefix, order, visit) + } + return res && visit(prefix, n) + + case RLV, Descending: + res := true + for i := len(n.children) - 1; i >= 0; i-- { + res = res && t._traverse(n.children[i], prefix, order, visit) + } + return res && visit(prefix, n) + + default: + return false + } +} + +// Graphviz generates and returns a string representation of the radix trie in DOT format. +// This format is commonly used for visualizing graphs with Graphviz tools. +func (t *radix[V]) Graphviz() string { + // Create a map of node --> id + var id int + nodeID := map[*radixNode[V]]int{} + t._traverse(t.root, "", VLR, func(_ string, n *radixNode[V]) bool { + id++ + nodeID[n] = id + return true + }) + + graph := graphviz.NewGraph(true, true, false, "Radix Tree", graphviz.RankDirTB, "", "", graphviz.ShapeMrecord) + + t._traverse(t.root, "", VLR, func(_ string, n *radixNode[V]) bool { + name := fmt.Sprintf("%d", nodeID[n]) + + var label string + var style graphviz.Style + var topField graphviz.Field + + switch { + case n == t.root: + label = "•" + topField = graphviz.NewSimpleField("", label) + case !n.term: + label = string(n.label) + topField = graphviz.NewSimpleField("", label) + default: + label = string(n.label) + style = graphviz.StyleBold + topField = graphviz.NewComplexField( + graphviz.NewRecord( + graphviz.NewSimpleField("", label), + graphviz.NewSimpleField("", fmt.Sprintf("%v", n.val)), + ), + ) + } + + bottomRec := graphviz.NewRecord() + for _, e := range n.children { + edgeName := string(e.label) + from := fmt.Sprintf("%s:%s", name, edgeName) + to := fmt.Sprintf("%d", nodeID[e]) + + bottomRec.AddField(graphviz.NewSimpleField(edgeName, "")) + graph.AddEdge(graphviz.NewEdge(from, to, graphviz.EdgeTypeDirected, "", "", "", "", "", "")) + } + + rec := graphviz.NewRecord( + graphviz.NewComplexField( + graphviz.NewRecord( + topField, + graphviz.NewComplexField(bottomRec), + ), + ), + ) + + graph.AddNode(graphviz.NewNode(name, "", rec.Label(), "", style, "", "", "")) + + return true + }) + + return graph.DotCode() +} diff --git a/trie/radix_test.go b/trie/radix_test.go new file mode 100644 index 0000000..f3d79b0 --- /dev/null +++ b/trie/radix_test.go @@ -0,0 +1,78 @@ +package trie + +import ( + "testing" + + . "github.com/moorara/algo/generic" +) + +func getRadixTests() []trieTest[int] { + tests := getTrieTests() + + tests[0].trie = "Radix Trie" + tests[0].expectedHeight = 3 + tests[0].equals = nil + tests[0].expectedEquals = false + tests[0].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedLVRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedRVLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedLRVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedRLVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[0].expectedGraphviz = `` + + tests[1].trie = "Radix Trie" + tests[1].expectedHeight = 5 + tests[1].equals = NewRadix[int](nil) + tests[1].expectedEquals = false + tests[1].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedLVRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedRVLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedLRVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedRLVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[1].expectedGraphviz = `` + + tests[2].trie = "Radix Trie" + tests[2].expectedHeight = 7 + tests[2].equals = NewRadix[int](nil) + tests[2].expectedEquals = false + tests[2].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedLVRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedRVLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedLRVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedRLVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[2].expectedGraphviz = `` + + tests[3].trie = "Radix Trie" + tests[3].expectedHeight = 8 + tests[3].equals = NewRadix[int](nil) + tests[3].expectedEquals = true + tests[3].expectedVLRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedVRLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 7}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedLVRTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedRVLTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedLRVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedRLVTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedAscendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedDescendingTraverse = []KeyValue[string, int]{{Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}, {Key: "", Val: 0}} + tests[3].expectedGraphviz = `` + + return tests +} + +func TestRadixTrie(t *testing.T) { + tests := getRadixTests() + + for _, tc := range tests { + bin := NewRadix[int](tc.eqVal) + runTrieTest(t, bin, tc) + } +}