1
+ //! This module provides a generic implementation of a Trie (prefix tree).
2
+ //! A Trie is a tree-like data structure that is commonly used to store sequences of keys
3
+ //! (such as strings, integers, or other iterable types) where each node represents one element
4
+ //! of the key, and values can be associated with full sequences.
5
+
1
6
use std:: collections:: HashMap ;
2
7
use std:: hash:: Hash ;
3
8
9
+ /// A single node in the Trie structure, representing a key and an optional value.
4
10
#[ derive( Debug , Default ) ]
5
11
struct Node < Key : Default , Type : Default > {
12
+ /// A map of children nodes where each key maps to another `Node`.
6
13
children : HashMap < Key , Node < Key , Type > > ,
14
+ /// The value associated with this node, if any.
7
15
value : Option < Type > ,
8
16
}
9
17
18
+ /// A generic Trie (prefix tree) data structure that allows insertion and lookup
19
+ /// based on a sequence of keys.
10
20
#[ derive( Debug , Default ) ]
11
21
pub struct Trie < Key , Type >
12
22
where
13
23
Key : Default + Eq + Hash ,
14
24
Type : Default ,
15
25
{
26
+ /// The root node of the Trie, which does not hold a value itself.
16
27
root : Node < Key , Type > ,
17
28
}
18
29
@@ -21,12 +32,21 @@ where
21
32
Key : Default + Eq + Hash ,
22
33
Type : Default ,
23
34
{
35
+ /// Creates a new, empty `Trie`.
36
+ ///
37
+ /// # Returns
38
+ /// A `Trie` instance with an empty root node.
24
39
pub fn new ( ) -> Self {
25
40
Self {
26
41
root : Node :: default ( ) ,
27
42
}
28
43
}
29
44
45
+ /// Inserts a value into the Trie, associating it with a sequence of keys.
46
+ ///
47
+ /// # Arguments
48
+ /// - `key`: An iterable sequence of keys (e.g., characters in a string or integers in a vector).
49
+ /// - `value`: The value to associate with the sequence of keys.
30
50
pub fn insert ( & mut self , key : impl IntoIterator < Item = Key > , value : Type )
31
51
where
32
52
Key : Eq + Hash ,
@@ -38,60 +58,98 @@ where
38
58
node. value = Some ( value) ;
39
59
}
40
60
61
+ /// Retrieves a reference to the value associated with a sequence of keys, if it exists.
62
+ ///
63
+ /// # Arguments
64
+ /// - `key`: An iterable sequence of keys (e.g., characters in a string or integers in a vector).
65
+ ///
66
+ /// # Returns
67
+ /// An `Option` containing a reference to the value if the sequence of keys exists in the Trie,
68
+ /// or `None` if it does not.
41
69
pub fn get ( & self , key : impl IntoIterator < Item = Key > ) -> Option < & Type >
42
70
where
43
71
Key : Eq + Hash ,
44
72
{
45
73
let mut node = & self . root ;
46
74
for c in key {
47
- if node. children . contains_key ( & c) {
48
- node = node. children . get ( & c) . unwrap ( )
49
- } else {
50
- return None ;
51
- }
75
+ node = node. children . get ( & c) ?;
52
76
}
53
77
node. value . as_ref ( )
54
78
}
55
79
}
56
80
57
81
#[ cfg( test) ]
58
82
mod tests {
59
-
60
83
use super :: * ;
61
84
62
85
#[ test]
63
- fn test_insertion ( ) {
86
+ fn test_insertion_and_retrieval_with_strings ( ) {
64
87
let mut trie = Trie :: new ( ) ;
65
- assert_eq ! ( trie. get( "" . chars( ) ) , None ) ;
66
88
67
89
trie. insert ( "foo" . chars ( ) , 1 ) ;
90
+ assert_eq ! ( trie. get( "foo" . chars( ) ) , Some ( & 1 ) ) ;
68
91
trie. insert ( "foobar" . chars ( ) , 2 ) ;
92
+ assert_eq ! ( trie. get( "foobar" . chars( ) ) , Some ( & 2 ) ) ;
93
+ assert_eq ! ( trie. get( "foo" . chars( ) ) , Some ( & 1 ) ) ;
94
+ trie. insert ( "bar" . chars ( ) , 3 ) ;
95
+ assert_eq ! ( trie. get( "bar" . chars( ) ) , Some ( & 3 ) ) ;
96
+ assert_eq ! ( trie. get( "baz" . chars( ) ) , None ) ;
97
+ assert_eq ! ( trie. get( "foobarbaz" . chars( ) ) , None ) ;
98
+ }
69
99
100
+ #[ test]
101
+ fn test_insertion_and_retrieval_with_integers ( ) {
70
102
let mut trie = Trie :: new ( ) ;
71
- assert_eq ! ( trie. get( vec![ 1 , 2 , 3 ] ) , None ) ;
72
103
73
104
trie. insert ( vec ! [ 1 , 2 , 3 ] , 1 ) ;
74
- trie. insert ( vec ! [ 3 , 4 , 5 ] , 2 ) ;
105
+ assert_eq ! ( trie. get( vec![ 1 , 2 , 3 ] ) , Some ( & 1 ) ) ;
106
+ trie. insert ( vec ! [ 1 , 2 , 3 , 4 , 5 ] , 2 ) ;
107
+ assert_eq ! ( trie. get( vec![ 1 , 2 , 3 , 4 , 5 ] ) , Some ( & 2 ) ) ;
108
+ assert_eq ! ( trie. get( vec![ 1 , 2 , 3 ] ) , Some ( & 1 ) ) ;
109
+ trie. insert ( vec ! [ 10 , 20 , 30 ] , 3 ) ;
110
+ assert_eq ! ( trie. get( vec![ 10 , 20 , 30 ] ) , Some ( & 3 ) ) ;
111
+ assert_eq ! ( trie. get( vec![ 4 , 5 , 6 ] ) , None ) ;
112
+ assert_eq ! ( trie. get( vec![ 1 , 2 , 3 , 4 , 5 , 6 ] ) , None ) ;
75
113
}
76
114
77
115
#[ test]
78
- fn test_get ( ) {
116
+ fn test_empty_trie ( ) {
117
+ let trie: Trie < char , i32 > = Trie :: new ( ) ;
118
+
119
+ assert_eq ! ( trie. get( "foo" . chars( ) ) , None ) ;
120
+ assert_eq ! ( trie. get( "" . chars( ) ) , None ) ;
121
+ }
122
+
123
+ #[ test]
124
+ fn test_insert_empty_key ( ) {
125
+ let mut trie: Trie < char , i32 > = Trie :: new ( ) ;
126
+
127
+ trie. insert ( "" . chars ( ) , 42 ) ;
128
+ assert_eq ! ( trie. get( "" . chars( ) ) , Some ( & 42 ) ) ;
129
+ assert_eq ! ( trie. get( "foo" . chars( ) ) , None ) ;
130
+ }
131
+
132
+ #[ test]
133
+ fn test_overlapping_keys ( ) {
79
134
let mut trie = Trie :: new ( ) ;
80
- trie. insert ( "foo" . chars ( ) , 1 ) ;
81
- trie. insert ( "foobar" . chars ( ) , 2 ) ;
82
- trie. insert ( "bar" . chars ( ) , 3 ) ;
83
- trie. insert ( "baz" . chars ( ) , 4 ) ;
84
135
85
- assert_eq ! ( trie. get( "foo" . chars( ) ) , Some ( & 1 ) ) ;
86
- assert_eq ! ( trie. get( "food" . chars( ) ) , None ) ;
136
+ trie. insert ( "car" . chars ( ) , 1 ) ;
137
+ trie. insert ( "cart" . chars ( ) , 2 ) ;
138
+ trie. insert ( "carter" . chars ( ) , 3 ) ;
139
+ assert_eq ! ( trie. get( "car" . chars( ) ) , Some ( & 1 ) ) ;
140
+ assert_eq ! ( trie. get( "cart" . chars( ) ) , Some ( & 2 ) ) ;
141
+ assert_eq ! ( trie. get( "carter" . chars( ) ) , Some ( & 3 ) ) ;
142
+ assert_eq ! ( trie. get( "care" . chars( ) ) , None ) ;
143
+ }
87
144
145
+ #[ test]
146
+ fn test_partial_match ( ) {
88
147
let mut trie = Trie :: new ( ) ;
89
- trie. insert ( vec ! [ 1 , 2 , 3 , 4 ] , 1 ) ;
90
- trie. insert ( vec ! [ 42 ] , 2 ) ;
91
- trie. insert ( vec ! [ 42 , 6 , 1000 ] , 3 ) ;
92
- trie. insert ( vec ! [ 1 , 2 , 4 , 16 , 32 ] , 4 ) ;
93
148
94
- assert_eq ! ( trie. get( vec![ 42 , 6 , 1000 ] ) , Some ( & 3 ) ) ;
95
- assert_eq ! ( trie. get( vec![ 43 , 44 , 45 ] ) , None ) ;
149
+ trie. insert ( "apple" . chars ( ) , 10 ) ;
150
+ assert_eq ! ( trie. get( "app" . chars( ) ) , None ) ;
151
+ assert_eq ! ( trie. get( "appl" . chars( ) ) , None ) ;
152
+ assert_eq ! ( trie. get( "apple" . chars( ) ) , Some ( & 10 ) ) ;
153
+ assert_eq ! ( trie. get( "applepie" . chars( ) ) , None ) ;
96
154
}
97
155
}
0 commit comments