1
+ /// Iternal macro helper functions.
2
+ #[ cfg( feature = "tree_macros_internals" ) ]
3
+ #[ doc( hidden) ]
4
+ pub mod helper_functions;
5
+
1
6
///////////////////////////////////////////////////////////////////////////////////////////////////
2
7
// List Node macros
3
8
///////////////////////////////////////////////////////////////////////////////////////////////////
6
11
///
7
12
/// A macro to reduce the boilerplate in generating a full ListNode.
8
13
///
14
+ /// ## Match arms
15
+ ///
16
+ /// Arm 1:
17
+ /// - Takes the value as an argument.
18
+ /// - Equivalent of doing `ListNode::new()`.
19
+ ///
20
+ /// Arm 2:
21
+ /// - Takes the value as an argument.
22
+ /// - Also takes a sequence of left and right node values at the same time (which means they're
23
+ /// symmetric) as an argument (and builds the `ListNode` struct with them).
24
+ ///
9
25
/// ## Example
10
26
///
11
27
/// This code:
@@ -52,38 +68,194 @@ macro_rules! list_node {
52
68
// Tree Node macros
53
69
///////////////////////////////////////////////////////////////////////////////////////////////////
54
70
55
- /// TODO:
56
- /// You can generate TreeNodes manually by utilizing tuples. The first value is a single value and
57
- /// everything else is a tuple of `(Option<i32>, Option<i32>)`
58
- // #[macro_export]
59
- #[ allow( unused_macros) ]
71
+ /// ## Description
72
+ ///
73
+ /// You can generate TreeNodes manually by utilizing a `[Vec<Option<i32>]` data structure.
74
+ ///
75
+ /// **IMPORTANT:** Whenever you have more Nodes and there's a None node above - It's up to you to
76
+ /// make sure that the nodes are matched correctly. Whenever there's a `None` value at a level
77
+ /// that's not the last one then the next level will ignore every impossible value. This means that
78
+ /// if you want this tree:
79
+ ///
80
+ /// ```markdown
81
+ /// Some(100) // Root Node
82
+ /// / \
83
+ /// None Some(21) // Left and Right nodes respectively
84
+ /// / \
85
+ /// None None
86
+ /// ```
87
+ ///
88
+ /// You need to call the macro like this:
89
+ ///
90
+ /// ```rust
91
+ /// use std::{rc::Rc, cell::RefCell};
92
+ /// use leetcode_trees_rs::utils::{tree, TreeNode};
93
+ ///
94
+ /// let tree = tree!(
95
+ /// &[
96
+ /// vec![Some(100)],
97
+ /// vec![None, Some(21)],
98
+ /// vec![Some(11), None], // **DON'T** use 4 `Option` values! The first two are inferred!
99
+ /// ]
100
+ /// );
101
+ ///
102
+ /// assert_eq!(
103
+ /// tree,
104
+ /// Some(Rc::new(RefCell::new(TreeNode {
105
+ /// val: 100,
106
+ /// left: None,
107
+ /// right: Some(Rc::new(RefCell::new(TreeNode {
108
+ /// val: 21,
109
+ /// left: Some(Rc::new(RefCell::new(TreeNode::new(11)))),
110
+ /// right: None
111
+ /// })))
112
+ /// })))
113
+ /// );
114
+ /// ```
115
+ ///
116
+ /// Another important note: If the `None` value is a the end of a vec like this:
117
+ ///
118
+ /// ```rust
119
+ /// use std::{rc::Rc, cell::RefCell};
120
+ /// use leetcode_trees_rs::utils::{tree, TreeNode};
121
+ ///
122
+ /// let tree = tree!(
123
+ /// &[
124
+ /// vec![Some(100)],
125
+ /// vec![Some(21), None], // ! You need to have that trialing None !
126
+ /// vec![Some(11)], // Otherwise this `11` will get written to root->right rather
127
+ /// // than of root->left->left.
128
+ /// ]
129
+ /// );
130
+ ///
131
+ /// assert_eq!(
132
+ /// tree,
133
+ /// Some(Rc::new(RefCell::new(TreeNode {
134
+ /// val: 100,
135
+ /// left: Some(Rc::new(RefCell::new(TreeNode {
136
+ /// val: 21,
137
+ /// left: Some(Rc::new(RefCell::new(TreeNode::new(11)))),
138
+ /// right: None
139
+ /// }))),
140
+ /// right: None
141
+ /// })))
142
+ /// );
143
+ /// ```
144
+ ///
145
+ /// ## Match arms
146
+ ///
147
+ /// Arm 1:
148
+ /// - Takes the `[Vec<Option<i32>>]` data type which contains the `TreeNode` values based on the
149
+ /// description for this macro.
150
+ ///
151
+ ///
152
+ /// ## Additional examples
153
+ ///
154
+ /// Making a tree only towards the left side:
155
+ ///
156
+ /// ```rust
157
+ /// use std::{cell::RefCell, rc::Rc};
158
+ /// use leetcode_trees_rs::utils::{tree, symmetric_tree, TreeNode};
159
+ ///
160
+ /// let node_left_sided = TreeNode {
161
+ /// val: 1,
162
+ /// left: Some(Rc::new(RefCell::new(TreeNode {
163
+ /// val: 2,
164
+ /// left: Some(Rc::new(RefCell::new(TreeNode::new(5)))),
165
+ /// right: Some(Rc::new(RefCell::new(TreeNode::new(6)))),
166
+ /// }))),
167
+ /// right: None,
168
+ /// };
169
+ /// assert_eq!(
170
+ /// Rc::new(RefCell::new(node_left_sided)),
171
+ /// tree!(
172
+ /// &[
173
+ /// vec![Some(1)],
174
+ /// vec![Some(2), None], // (!) You need to specify any trailing `None` values.
175
+ /// vec![Some(5), Some(6), /* None, None */],
176
+ /// ]
177
+ /// ).expect("Failed to generate TreeNode from [Vec<i32>]")
178
+ /// );
179
+ /// ```
180
+ ///
181
+ /// Making a tree only towards the right side:
182
+ ///
183
+ /// ```rust
184
+ /// use std::{cell::RefCell, rc::Rc};
185
+ /// use leetcode_trees_rs::utils::{tree, symmetric_tree, TreeNode};
186
+ ///
187
+ /// let node_right_sided = TreeNode {
188
+ /// val: 1,
189
+ /// left: None,
190
+ /// right: Some(Rc::new(RefCell::new(TreeNode {
191
+ /// val: 3,
192
+ /// left: Some(Rc::new(RefCell::new(TreeNode::new(7)))),
193
+ /// right: Some(Rc::new(RefCell::new(TreeNode::new(8)))),
194
+ /// }))),
195
+ /// };
196
+ /// assert_eq!(
197
+ /// Rc::new(RefCell::new(node_right_sided)),
198
+ /// tree!(
199
+ /// &[
200
+ /// vec![Some(1)],
201
+ /// vec![None, Some(3)],
202
+ /// // The other `None` values are inferred from their parents.
203
+ /// //
204
+ /// // **IMPORTANT:** Don't add them in because it causes errors!
205
+ /// vec![/*None, None, */ Some(7), Some(8)],
206
+ /// ]
207
+ /// ).expect("Failed to generate TreeNode from [Vec<i32>]")
208
+ /// );
209
+ /// ```
210
+ ///
211
+ /// Utilizig both sides in making a tree:
212
+ ///
213
+ /// ```rust
214
+ /// use std::{cell::RefCell, rc::Rc};
215
+ /// use leetcode_trees_rs::utils::{tree, symmetric_tree, TreeNode};
216
+ ///
217
+ /// let node_both_sided = TreeNode {
218
+ /// val: 1,
219
+ /// left: Some(Rc::new(RefCell::new(TreeNode {
220
+ /// val: 2,
221
+ /// left: Some(Rc::new(RefCell::new(TreeNode::new(5)))),
222
+ /// right: Some(Rc::new(RefCell::new(TreeNode::new(6)))),
223
+ /// }))),
224
+ /// right: Some(Rc::new(RefCell::new(TreeNode {
225
+ /// val: 3,
226
+ /// left: Some(Rc::new(RefCell::new(TreeNode::new(7)))),
227
+ /// right: Some(Rc::new(RefCell::new(TreeNode::new(8)))),
228
+ /// }))),
229
+ /// };
230
+ /// assert_eq!(
231
+ /// Rc::new(RefCell::new(node_both_sided)),
232
+ /// tree!(
233
+ /// &[
234
+ /// vec![Some(1)],
235
+ /// vec![Some(2), Some(3)],
236
+ /// vec![Some(5), Some(6), Some(7), Some(8)],
237
+ /// ]
238
+ /// ).expect("Failed to generate TreeNode from [Vec<i32>]")
239
+ /// );
240
+ /// ```
241
+ ///
242
+ /// ## Performance
243
+ ///
244
+ /// The way this is implemented is with depth traversal (similiar to [Breath-First
245
+ /// Search](https://en.wikipedia.org/wiki/Breadth-first_search)) so the algorithm's performance is:
246
+ ///
247
+ /// Worst-case time complexity: O(|V| + |E|) = O(b<sup>d</sup>)
248
+ ///
249
+ /// Worst-case space complexity: O(|V|) = O(b<sup>d</sup>)
250
+ ///
251
+ /// Where:
252
+ ///
253
+ /// V = Verticies and E = Edges
254
+ #[ macro_export]
60
255
macro_rules! tree {
61
- ( $val: expr) => {
62
- $crate:: utils:: TreeNode :: new( $val)
63
- } ;
64
- ( $( $left: tt, $right: tt) * ) => {
65
- $(
66
- if let Some ( left) = $left {
67
- $node. left = Some ( std:: rc:: Rc :: new( std:: cell:: RefCell :: new( tree!(
68
- left
69
- ) ) ) ) ;
70
- }
71
- if let Some ( right) = $right {
72
- $node. right = Some ( std:: rc:: Rc :: new( std:: cell:: RefCell :: new( tree!(
73
- right
74
- ) ) ) ) ;
75
- }
76
- ) *
77
- } ;
78
- ( $val: expr, $( $left: expr, $right: expr) * ) => {
79
- {
80
- let mut node = $crate:: utils:: TreeNode :: new( $val) ;
81
- $(
82
- tree!( node, ( $left, $right) ) ;
83
- ) *
84
- node
85
- }
86
- } ;
256
+ ( $items: expr) => { {
257
+ $crate:: macros:: helper_functions:: _build_tree( $items)
258
+ } } ;
87
259
}
88
260
89
261
/// ## Description
@@ -102,6 +274,7 @@ macro_rules! tree {
102
274
/// symmetric) as an argument (and builds the `TreeNode` struct with them).
103
275
///
104
276
/// ## Example usage
277
+ ///
105
278
/// ```rust
106
279
/// use leetcode_trees_rs::utils::symmetric_tree;
107
280
/// symmetric_tree!(1, 2, 3, 4);
@@ -175,6 +348,23 @@ macro_rules! tree {
175
348
/// };
176
349
/// assert_eq!(node, symmetric_tree!(1, 2, 3, 4));
177
350
/// ```
351
+ ///
352
+ /// Another way of desugaring this symmetric tree is with the tree!() macro like so:
353
+ ///
354
+ /// ```rust
355
+ /// use std::{rc::Rc, cell::RefCell};
356
+ /// use leetcode_trees_rs::utils::{symmetric_tree, tree};
357
+ /// assert_eq!(
358
+ /// tree!(
359
+ /// &mut [
360
+ /// vec![Some(1)],
361
+ /// vec![Some(2), Some(2)],
362
+ /// vec![Some(3), Some(3), Some(3), Some(3)],
363
+ /// vec![Some(4), Some(4), Some(4), Some(4), Some(4), Some(4), Some(4), Some(4)],
364
+ /// ]
365
+ /// ).unwrap(),
366
+ /// Rc::new(RefCell::new(symmetric_tree!(1, 2, 3, 4))));
367
+ /// ```
178
368
#[ macro_export]
179
369
macro_rules! symmetric_tree {
180
370
( $val: expr) => {
0 commit comments