@@ -497,6 +497,7 @@ impl Tree {
497
497
) -> Box < dyn Iterator < Item = NodeId > + ' _ > {
498
498
match order {
499
499
NodeTraversalOrder :: Preorder => Box :: new ( PreorderNodeIterator :: new ( self ) ) ,
500
+ NodeTraversalOrder :: Postorder => Box :: new ( PostorderNodeIterator :: new ( self ) ) ,
500
501
}
501
502
}
502
503
@@ -621,6 +622,10 @@ pub enum NodeTraversalOrder {
621
622
///For trees with multiple roots, start at the left root,
622
623
///traverse to tips, proceeed to the next root, etc..
623
624
Preorder ,
625
+ ///Postorder traversal, starting at the root(s) of a [`Tree`].
626
+ ///For trees with multiple roots, start at the left root,
627
+ ///traverse to tips, proceeed to the next root, etc..
628
+ Postorder ,
624
629
}
625
630
626
631
struct PreorderNodeIterator < ' a > {
@@ -663,6 +668,11 @@ impl NodeIterator for PreorderNodeIterator<'_> {
663
668
None => {
664
669
if let Some ( r) = self . root_stack . pop ( ) {
665
670
self . current_node_ = Some ( r) ;
671
+ let mut c = self . tree . right_child ( r) . unwrap ( ) ;
672
+ while c != NodeId :: NULL {
673
+ self . node_stack . push ( c) ;
674
+ c = self . tree . left_sib ( c) . unwrap ( ) ;
675
+ }
666
676
}
667
677
}
668
678
} ;
@@ -675,6 +685,64 @@ impl NodeIterator for PreorderNodeIterator<'_> {
675
685
676
686
iterator_for_nodeiterator ! ( PreorderNodeIterator <' _>) ;
677
687
688
+ struct PostorderNodeIterator < ' a > {
689
+ nodes : Vec < NodeId > ,
690
+ current_node_index : usize ,
691
+ num_nodes_current_tree : usize ,
692
+ // Make the lifetime checker happy.
693
+ tree : std:: marker:: PhantomData < & ' a Tree > ,
694
+ }
695
+
696
+ impl < ' a > PostorderNodeIterator < ' a > {
697
+ fn new ( tree : & ' a Tree ) -> Self {
698
+ let mut num_nodes_current_tree: usize = 0 ;
699
+ let ptr = std:: ptr:: addr_of_mut!( num_nodes_current_tree) ;
700
+ let mut nodes = vec ! [
701
+ NodeId :: NULL ;
702
+ // NOTE: this fn does not return error codes
703
+ unsafe { ll_bindings:: tsk_tree_get_size_bound( tree. inner) } as usize
704
+ ] ;
705
+
706
+ let rv = unsafe {
707
+ ll_bindings:: tsk_tree_postorder (
708
+ tree. inner ,
709
+ NodeId :: NULL . into ( ) , // start from virtual root
710
+ nodes. as_mut_ptr ( ) as * mut tsk_id_t ,
711
+ ptr as * mut tsk_size_t ,
712
+ )
713
+ } ;
714
+
715
+ // This is either out of memory
716
+ // or node out of range.
717
+ // The former is fatal, and the latter
718
+ // not relevant (for now), as we start at roots.
719
+ if rv < 0 {
720
+ panic ! ( "fatal error calculating postoder node list" ) ;
721
+ }
722
+
723
+ Self {
724
+ nodes,
725
+ current_node_index : 0 ,
726
+ num_nodes_current_tree,
727
+ tree : std:: marker:: PhantomData ,
728
+ }
729
+ }
730
+ }
731
+
732
+ impl < ' a > Iterator for PostorderNodeIterator < ' a > {
733
+ type Item = NodeId ;
734
+ fn next ( & mut self ) -> Option < Self :: Item > {
735
+ match self . current_node_index < self . num_nodes_current_tree {
736
+ true => {
737
+ let rv = self . nodes [ self . current_node_index ] ;
738
+ self . current_node_index += 1 ;
739
+ Some ( rv)
740
+ }
741
+ false => None ,
742
+ }
743
+ }
744
+ }
745
+
678
746
struct RootIterator < ' a > {
679
747
current_root : Option < NodeId > ,
680
748
next_root : NodeId ,
@@ -1320,14 +1388,50 @@ pub(crate) mod test_trees {
1320
1388
assert_eq ! ( treeseq. num_trees( ) , 2 ) ;
1321
1389
let mut tree_iter = treeseq. tree_iterator ( TreeFlags :: SAMPLE_LISTS ) . unwrap ( ) ;
1322
1390
while let Some ( tree) = tree_iter. next ( ) {
1391
+ let mut preoder_nodes = vec ! [ ] ;
1392
+ let mut postoder_nodes = vec ! [ ] ;
1323
1393
for n in tree. traverse_nodes ( NodeTraversalOrder :: Preorder ) {
1324
1394
let mut nsamples = 0 ;
1395
+ preoder_nodes. push ( n) ;
1325
1396
for _ in tree. samples ( n) . unwrap ( ) {
1326
1397
nsamples += 1 ;
1327
1398
}
1328
1399
assert ! ( nsamples > 0 ) ;
1329
1400
assert_eq ! ( nsamples, tree. num_tracked_samples( n) . unwrap( ) ) ;
1330
1401
}
1402
+ for n in tree. traverse_nodes ( NodeTraversalOrder :: Postorder ) {
1403
+ let mut nsamples = 0 ;
1404
+ postoder_nodes. push ( n) ;
1405
+ for _ in tree. samples ( n) . unwrap ( ) {
1406
+ nsamples += 1 ;
1407
+ }
1408
+ assert ! ( nsamples > 0 ) ;
1409
+ assert_eq ! ( nsamples, tree. num_tracked_samples( n) . unwrap( ) ) ;
1410
+ }
1411
+ assert_eq ! ( preoder_nodes. len( ) , postoder_nodes. len( ) ) ;
1412
+
1413
+ // Test our preorder against the tskit functions in 0.99.15
1414
+ {
1415
+ let mut nodes: Vec < NodeId > = vec ! [
1416
+ NodeId :: NULL ;
1417
+ unsafe { ll_bindings:: tsk_tree_get_size_bound( tree. as_ptr( ) ) }
1418
+ as usize
1419
+ ] ;
1420
+ let mut num_nodes: tsk_size_t = 0 ;
1421
+ let ptr = std:: ptr:: addr_of_mut!( num_nodes) ;
1422
+ unsafe {
1423
+ ll_bindings:: tsk_tree_preorder (
1424
+ tree. as_ptr ( ) ,
1425
+ -1 ,
1426
+ nodes. as_mut_ptr ( ) as * mut tsk_id_t ,
1427
+ ptr,
1428
+ ) ;
1429
+ }
1430
+ assert_eq ! ( num_nodes as usize , preoder_nodes. len( ) ) ;
1431
+ for i in 0 ..num_nodes as usize {
1432
+ assert_eq ! ( preoder_nodes[ i] , nodes[ i] ) ;
1433
+ }
1434
+ }
1331
1435
}
1332
1436
}
1333
1437
0 commit comments