@@ -2142,7 +2142,7 @@ where
21422142 /// * [`Dfs`] for (pre-order) depth-first ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Depth-first_search))
21432143 /// * [`PostOrder`] for post-order ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Post-order,_LRN))
21442144 ///
2145- /// As opposed to [`walk_mut`], this method does require internal allocation.
2145+ /// As opposed to [`walk_mut`], this method does not require internal allocation.
21462146 /// Furthermore, it allows to attach node depths or sibling indices to the yield values.
21472147 /// Please see the examples below.
21482148 ///
@@ -2371,7 +2371,7 @@ where
23712371 /// assert!(tree.is_empty());
23722372 /// assert_eq!(tree.get_root(), None);
23732373 /// ```
2374- pub fn into_walk < T > ( self ) -> impl Iterator < Item = V :: Item > + use < ' a , T , V , M , P , MO >
2374+ pub fn into_walk < T > ( self ) -> impl Iterator < Item = V :: Item >
23752375 where
23762376 T : Traverser < OverData > ,
23772377 {
@@ -2390,7 +2390,7 @@ where
23902390 /// * [`Dfs`] for (pre-order) depth-first ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Depth-first_search))
23912391 /// * [`PostOrder`] for post-order ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Post-order,_LRN))
23922392 ///
2393- /// As opposed to [`into_walk`], this method does require internal allocation.
2393+ /// As opposed to [`into_walk`], this method does not require internal allocation.
23942394 /// Furthermore, it allows to attach node depths or sibling indices to the yield values.
23952395 /// Please see the examples below.
23962396 ///
@@ -2623,7 +2623,7 @@ where
26232623 /// * [`Dfs`] for (pre-order) depth-first ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Depth-first_search))
26242624 /// * [`PostOrder`] for post-order ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Post-order,_LRN))
26252625 ///
2626- /// As opposed to [`leaves_mut`], this method does require internal allocation.
2626+ /// As opposed to [`leaves_mut`], this method does not require internal allocation.
26272627 /// Furthermore, it allows to attach node depths or sibling indices to the yield values.
26282628 /// Please see the examples below.
26292629 ///
@@ -2755,6 +2755,197 @@ where
27552755 } )
27562756 }
27572757
2758+ /// Creates an iterator that yields owned (removed) data of all leaves of the subtree rooted at this node.
2759+ ///
2760+ /// Note that once the returned iterator is dropped, regardless of whether it is completely used up or not,
2761+ /// the subtree rooted at this node will be **removed** from the tree it belongs to.
2762+ /// If this node is the root of the tree, the tree will be left empty.
2763+ ///
2764+ /// The order of the elements is determined by the generic [`Traverser`] parameter `T`.
2765+ /// Available implementations are:
2766+ /// * [`Bfs`] for breadth-first ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Breadth-first_search))
2767+ /// * [`Dfs`] for (pre-order) depth-first ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Depth-first_search))
2768+ /// * [`PostOrder`] for post-order ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Post-order,_LRN))
2769+ ///
2770+ /// See also [`leaves`] and [`leaves_mut`] for iterators over shared and mutable references, respectively.
2771+ ///
2772+ /// Note that tree traversing methods typically allocate a temporary data structure that is dropped once the
2773+ /// iterator is dropped.
2774+ /// In use cases where we repeatedly iterate using any of the **leaves** methods over different nodes or different
2775+ /// trees, we can avoid the allocation by creating the traverser only once and using [`leaves_with`], [`leaves_mut_with`]
2776+ /// and [`into_leaves_with`] methods instead.
2777+ /// These methods additionally allow for iterating over nodes rather than data; and yielding node depths and sibling
2778+ /// indices in addition to node data.
2779+ ///
2780+ /// > **(!)** As a method that removes nodes from the tree, this method might result in invalidating indices that are
2781+ /// > cached earlier in the [`Auto`] mode, but not in the [`Lazy`] mode. Please see the documentation of [MemoryPolicy]
2782+ /// > for details of node index validity. Specifically, the examples in the "Lazy Memory Claim: Preventing Invalid Indices"
2783+ /// > section presents a convenient way that allows us to make sure that the indices are valid.
2784+ ///
2785+ /// [`Auto`]: crate::Auto
2786+ /// [`Lazy`]: crate::Lazy
2787+ /// [`MemoryPolicy`]: crate::MemoryPolicy
2788+ ///
2789+ /// [`Bfs`]: crate::Bfs
2790+ /// [`Dfs`]: crate::Dfs
2791+ /// [`PostOrder`]: crate::PostOrder
2792+ /// [`leaves`]: crate::NodeRef::leaves
2793+ /// [`leaves_mut`]: crate::NodeMut::walk_mut
2794+ /// [`leaves_with`]: crate::NodeRef::leaves_with
2795+ /// [`leaves_mut_with`]: crate::NodeMut::leaves_mut_with
2796+ /// [`into_leaves_with`]: crate::NodeMut::into_leaves_with
2797+ ///
2798+ /// # Examples
2799+ ///
2800+ /// ```
2801+ /// use orx_tree::*;
2802+ ///
2803+ /// // 1
2804+ /// // ╱ ╲
2805+ /// // ╱ ╲
2806+ /// // 2 3
2807+ /// // ╱ ╲ ╱ ╲
2808+ /// // 4 5 6 7
2809+ /// // | | ╱ ╲
2810+ /// // 8 9 10 11
2811+ ///
2812+ /// let mut tree = DynTree::new(1);
2813+ /// let [id2, id3] = tree.root_mut().push_children([2, 3]);
2814+ /// let [id4, _] = tree.node_mut(id2).push_children([4, 5]);
2815+ /// tree.node_mut(id4).push_child(8);
2816+ /// let [id6, id7] = tree.node_mut(id3).push_children([6, 7]);
2817+ /// tree.node_mut(id6).push_child(9);
2818+ /// tree.node_mut(id7).push_children([10, 11]);
2819+ ///
2820+ /// // keep indices valid during removals
2821+ /// let mut tree = tree.into_lazy_reclaim();
2822+ ///
2823+ /// let n3 = tree.node_mut(id3);
2824+ /// let leaves: Vec<_> = n3.into_leaves::<Dfs>().collect();
2825+ /// assert_eq!(leaves, [9, 10, 11]);
2826+ ///
2827+ /// // 1
2828+ /// // ╱
2829+ /// // ╱
2830+ /// // 2
2831+ /// // ╱ ╲
2832+ /// // 4 5
2833+ /// // |
2834+ /// // 8
2835+ /// let remaining: Vec<_> = tree.root().walk::<Dfs>().copied().collect();
2836+ /// assert_eq!(remaining, [1, 2, 4, 8, 5]);
2837+ ///
2838+ /// let leaves: Vec<_> = tree.root_mut().into_leaves::<Dfs>().collect();
2839+ /// assert_eq!(leaves, [8, 5]);
2840+ ///
2841+ /// assert!(tree.is_empty());
2842+ /// ```
2843+ pub fn into_leaves < T > ( self ) -> impl Iterator < Item = V :: Item >
2844+ where
2845+ T : Traverser < OverData > ,
2846+ {
2847+ let storage = T :: Storage :: < V > :: default ( ) ;
2848+ T :: into_iter_with_storage_filtered ( self , storage, |x| {
2849+ let ptr = <<OverData as Over >:: Enumeration as Enumeration >:: node_data ( & x) ;
2850+ unsafe { & * ptr. ptr ( ) } . next ( ) . is_empty ( )
2851+ } )
2852+ }
2853+
2854+ /// Creates an iterator that yields owned (removed) data of all leaves of the subtree rooted at this node.
2855+ ///
2856+ /// Note that once the returned iterator is dropped, regardless of whether it is completely used up or not,
2857+ /// the subtree rooted at this node will be **removed** from the tree it belongs to.
2858+ /// If this node is the root of the tree, the tree will be left empty.
2859+ ///
2860+ /// The order of the elements is determined by the type of the `traverser` which implements [`Traverser`].
2861+ /// Available implementations are:
2862+ /// * [`Bfs`] for breadth-first ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Breadth-first_search))
2863+ /// * [`Dfs`] for (pre-order) depth-first ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Depth-first_search))
2864+ /// * [`PostOrder`] for post-order ([wikipedia](https://en.wikipedia.org/wiki/Tree_traversal#Post-order,_LRN))
2865+ ///
2866+ /// As opposed to [`into_leaves`], this method does not require internal allocation.
2867+ /// Furthermore, it allows to attach node depths or sibling indices to the yield values.
2868+ /// Please see the examples below.
2869+ ///
2870+ /// [`into_leaves`]: crate::NodeMut::into_leaves
2871+ /// [`Bfs`]: crate::Bfs
2872+ /// [`Dfs`]: crate::Dfs
2873+ /// [`PostOrder`]: crate::PostOrder
2874+ ///
2875+ /// > **(!)** As a method that removes nodes from the tree, this method might result in invalidating indices that are
2876+ /// > cached earlier in the [`Auto`] mode, but not in the [`Lazy`] mode. Please see the documentation of [MemoryPolicy]
2877+ /// > for details of node index validity. Specifically, the examples in the "Lazy Memory Claim: Preventing Invalid Indices"
2878+ /// > section presents a convenient way that allows us to make sure that the indices are valid.
2879+ ///
2880+ /// [`Auto`]: crate::Auto
2881+ /// [`Lazy`]: crate::Lazy
2882+ /// [`MemoryPolicy`]: crate::MemoryPolicy
2883+ ///
2884+ /// # Examples
2885+ ///
2886+ /// ```
2887+ /// use orx_tree::*;
2888+ ///
2889+ /// // 1
2890+ /// // ╱ ╲
2891+ /// // ╱ ╲
2892+ /// // 2 3
2893+ /// // ╱ ╲ ╱ ╲
2894+ /// // 4 5 6 7
2895+ /// // | | ╱ ╲
2896+ /// // 8 9 10 11
2897+ ///
2898+ /// let mut tree = DynTree::new(1);
2899+ /// let [id2, id3] = tree.root_mut().push_children([2, 3]);
2900+ /// let [id4, _] = tree.node_mut(id2).push_children([4, 5]);
2901+ /// tree.node_mut(id4).push_child(8);
2902+ /// let [id6, id7] = tree.node_mut(id3).push_children([6, 7]);
2903+ /// tree.node_mut(id6).push_child(9);
2904+ /// tree.node_mut(id7).push_children([10, 11]);
2905+ ///
2906+ /// // create the traverser 'dfs' only once, use it many times
2907+ /// // to walk over references, mutable references or removed values
2908+ /// // without additional allocation
2909+ ///
2910+ /// let mut dfs = Dfs::default();
2911+ ///
2912+ /// // keep indices valid during removals
2913+ /// let mut tree = tree.into_lazy_reclaim();
2914+ ///
2915+ /// let n3 = tree.node_mut(id3);
2916+ /// let leaves: Vec<_> = n3.into_leaves_with(&mut dfs).collect();
2917+ /// assert_eq!(leaves, [9, 10, 11]);
2918+ ///
2919+ /// // 1
2920+ /// // ╱
2921+ /// // ╱
2922+ /// // 2
2923+ /// // ╱ ╲
2924+ /// // 4 5
2925+ /// // |
2926+ /// // 8
2927+ /// let remaining: Vec<_> = tree.root().walk_with(&mut dfs).copied().collect();
2928+ /// assert_eq!(remaining, [1, 2, 4, 8, 5]);
2929+ ///
2930+ /// let leaves: Vec<_> = tree.root_mut().into_leaves_with(&mut dfs).collect();
2931+ /// assert_eq!(leaves, [8, 5]);
2932+ ///
2933+ /// assert!(tree.is_empty());
2934+ /// ```
2935+ pub fn into_leaves_with < T , O > (
2936+ self ,
2937+ traverser : & ' a mut T ,
2938+ ) -> impl Iterator < Item = OverItemInto < ' a , V , O > >
2939+ where
2940+ O : OverMut ,
2941+ T : Traverser < O > ,
2942+ {
2943+ T :: into_iter_with_storage_filtered ( self , traverser. storage_mut ( ) , |x| {
2944+ let ptr = <O :: Enumeration as Enumeration >:: node_data ( x) ;
2945+ unsafe { & * ptr. ptr ( ) } . next ( ) . is_empty ( )
2946+ } )
2947+ }
2948+
27582949 // recursive
27592950
27602951 /// Recursively sets the data of all nodes belonging to the subtree rooted at this node using the `compute_data`
0 commit comments