/// <summary> /// Post-order tree traversal method. /// </summary> /// /// <remarks> /// Adapted from John Cowan (1998) recommendation. /// </remarks> /// public static IEnumerator <DecisionNode> PostOrder(DecisionNode tree) { var cursor = new Dictionary <DecisionNode, int>(); DecisionNode currentNode = tree; while (currentNode != null) { // Move down to first child DecisionNode nextNode = null; if (currentNode.Branches != null) { nextNode = currentNode.Branches.FirstOrDefault(); } if (nextNode != null) { currentNode = nextNode; continue; } // No child nodes, so walk tree while (currentNode != null) { yield return(currentNode); // post order // Move to sibling if possible. nextNode = GetNextSibling(cursor, currentNode); if (nextNode != null) { currentNode = nextNode; break; } // Move up if (currentNode == nextNode) { currentNode = null; } else { currentNode = currentNode.Parent; } } } }
private void create(DecisionNode node, int depth) { string indent = new string(' ', depth * 4); if (!node.IsLeaf) { int attributeIndex = node.Branches.AttributeIndex; // Create all comparison expressions for (int i = 0; i < node.Branches.Count; i++) { DecisionNode child = node.Branches[i]; string cmp = ComparisonExtensions.ToString(child.Comparison); if (i == 0) { writer.Write(indent + "if "); } else { writer.Write(indent + "else if "); } string value = child.Value.Value.ToString(CultureInfo.InvariantCulture); writer.Write("(input[{0}] {1} {2}) {{", attributeIndex, cmp, value); writer.WriteLine(); create(child, depth + 1); writer.WriteLine(indent + "}"); } writer.WriteLine(indent + "else throw new ArgumentException(\"input\", \"Unexpected value at position " + attributeIndex + ".\");"); } else // node is a leaf { if (node.Output.HasValue) { string value = node.Output.Value.ToString(CultureInfo.InvariantCulture); writer.WriteLine(indent + "return " + value + ";"); } else { writer.WriteLine(indent + "return -1;"); } } }
/// <summary> /// Depth-first traversal method. /// </summary> /// public static IEnumerator <DecisionNode> DepthFirst(DecisionNode tree) { if (tree == null) { yield break; } var stack = new Stack <DecisionNode>(new[] { tree }); while (stack.Count != 0) { DecisionNode current = stack.Pop(); yield return(current); if (current.Branches != null) { for (int i = current.Branches.Count - 1; i >= 0; i--) { stack.Push(current.Branches[i]); } } } }
/// <summary> /// Breadth-first traversal method. /// </summary> /// public static IEnumerator <DecisionNode> BreadthFirst(DecisionNode tree) { if (tree == null) { yield break; } var queue = new Queue <DecisionNode>(new[] { tree }); while (queue.Count != 0) { DecisionNode current = queue.Dequeue(); yield return(current); if (current.Branches != null) { foreach (var child in current.Branches) { queue.Enqueue(child); } } } }
internal static DecisionNode GetNextSibling(Dictionary <DecisionNode, int> cursors, DecisionNode node) { var parent = node.Parent; if (parent == null) { return(null); } // Get current node index int index; if (!cursors.TryGetValue(node, out index)) { cursors[node] = index = 0; } int nextIndex = index + 1; if (nextIndex < parent.Branches.Count) { var sibling = parent.Branches[nextIndex]; cursors[sibling] = nextIndex; return(sibling); } return(null); }