private static IEnumerable <T> TraverseTree <T>(T root, Func <T, T> getLeftChild, Func <T, T> getRightChild, Func <T, T> getParent, TraversalKind traversalKind) where T : class { if (root == null) { throw new ArgumentNullException(nameof(root)); } if (getLeftChild == null) { throw new ArgumentNullException(nameof(getLeftChild)); } if (getRightChild == null) { throw new ArgumentNullException(nameof(getRightChild)); } if (getParent == null) { throw new ArgumentNullException(nameof(getParent)); } T previous = getParent(root); T current = root; while (current != null) { if (previous == getParent(current)) { if (traversalKind == TraversalKind.PreOrder) { yield return(current); } T left = getLeftChild(current); if (left == null) { previous = left; } else { previous = current; current = left; continue; } } if (previous == getLeftChild(current)) { if (traversalKind == TraversalKind.InOrder) { yield return(current); } T right = getRightChild(current); if (right == null) { previous = right; } else { previous = current; current = right; continue; } } if (previous == getRightChild(current)) { if (traversalKind == TraversalKind.PostOrder) { yield return(current); } previous = current; current = getParent(current); } } }
public void Traversal(char root, TraversalKind kind, string expected) { var actual = new string(root.Traverse(GetChildren, kind).ToArray()); Assert.AreEqual(expected, actual); }
/// <summary> /// Perform traversal of basic Tree-like structures or Graphs without cycles. /// Asymptotic worst case: O(n) /// Memory asymptotic worst case: O(n) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="root">Starting subtree root.</param> /// <param name="childrenProvider">Children provider for each node.</param> /// <param name="kind">Traversal algorithm to use.</param> /// <returns></returns> public static IEnumerable <T> Traverse <T>(this T root, Func <T, IEnumerable <T> > childrenProvider, TraversalKind kind = default(TraversalKind)) { if (childrenProvider == null) { throw new ArgumentNullException(nameof(childrenProvider)); } switch (kind) { case TraversalKind.ReverseInOrder: return(root.TraverseReverseInOrder(childrenProvider)); case TraversalKind.PreOrder: return(root.TraversePreOrder(childrenProvider)); case TraversalKind.PostOrder: return(root.TraversePostOrder(childrenProvider)); case TraversalKind.LevelOrder: return(root.TraverseLevelOrder(childrenProvider)); } throw new NotImplementedException(kind.ToString()); }