C# 3.0 Cookbook by Jay Hilyard, Stephen Teilhet This errata page lists errors outstanding in the most recent printing. If you have technical questions or error reports, you can send them to booktech@oreilly.com. Please specify the printing date of your copy. This page was updated February 8, 2008. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification Confirmed errors: {432} 11.5 There seems to be a couple of errors/omissions in the code. Here is the correct code - using System; using System.collections; using System.collections.Generic; public class NTree where T : IComparable { public NTree() { maxChildren = int.MaxValue; } public NTree(int maxNumChildren) { maxChildren = maxNumChildren; } // The root node of the tree private NTreeNodeFactory.NTreeNode root = null; // The maximum number of child nodes that a parent node may contain private int maxChildren = 0; public void AddRoot(NTreeNodeFactory.NTreeNode node) { root = node; } public NTreeNodeFactory.NTreeNode GetRoot() { return (root); } public int MaxChildren { get {return (maxChildren);} } } public class NTreeNodeFactory where T : IComparable { public NTreeNodeFactory(NTree root) { maxChildren = root.MaxChildren; } private int maxChildren = 0; public int MaxChildren { get {return (maxChildren);} } public NTreeNode CreateNode(T value) { return (new NTreeNode(value, maxChildren)); } // Nested Node class public class NTreeNode where U : IComparable { public NTreeNode(U value, int maxChildren) { if (!value.Equals(null)) { nodeValue = value; } childNodes = new NTreeNode[maxChildren]; } protected U nodeValue = default(U); protected NTreeNode[] childNodes = null; public int NumOfChildren { get {return (CountChildren());} } public int CountChildren() { int currCount = 0; for (int index = 0; index <= childNodes.GetUpperBound(0); index++) { if (childNodes[index] != null) { ++currCount; currCount += childNodes[index].CountChildren(); } } return (currCount); } public int CountImmediateChildren() { int currCount = 0; for (int index = 0; index <= childNodes.GetUpperBound(0); index++) { if (childNodes[index] != null) { ++currCount; } } return (currCount); } public NTreeNode[] Children { get {return (childNodes);} } public NTreeNode GetChild(int index) { return (childNodes[index]); } public U Value() { return (nodeValue); } public void AddNode(NTreeNode node) { int numOfNonNullNodes = CountImmediateChildren(); if (numOfNonNullNodes < childNodes.Length) { childNodes[numOfNonNullNodes] = node; } else { throw (new InvalidOperationException("Cannot add more children to this node.")); } } public NTreeNode DepthFirstSearch(U targetObj) { NTreeNode retObj = default(NTreeNode); if (targetObj.CompareTo(nodeValue) == 0) { retObj = this; } else { for (int index=0; index<=childNodes.GetUpperBound(0); index++) { if (childNodes[index] != null) { retObj = childNodes[index].DepthFirstSearch(targetObj); if (retObj != null) { break; } } } } return (retObj); } public NTreeNode BreadthFirstSearch(U targetObj) { Queue> row = new Queue>(); row.Enqueue(this); while (row.Count > 0) { // Get next node in queue NTreeNode currentNode = row.Dequeue(); // Is this the node we are looking for? if (targetObj.CompareTo(currentNode.nodeValue) == 0) { return (currentNode); } for (int index = 0; index < currentNode.CountImmediateChildren(); index++) { if (currentNode.Children[index] != null) { row.Enqueue(currentNode.Children[index]); } } } return (null); } public void PrintDepthFirst() { Console.WriteLine("this: " + nodeValue.ToString()); for (int index = 0; index < childNodes.Length; index++) { if (childNodes[index] != null) { Console.WriteLine("\tchildNodes[" + index + "]: " + childNodes[index].nodeValue.ToString()); } else { Console.WriteLine("\tchildNodes[" + index + "]: NULL"); } } for (int index = 0; index < childNodes.Length; index++) { if (childNodes[index] != null) { childNodes[index].PrintDepthFirst(); } } } public void RemoveNode(int index) { // Remove node from array and Compact the array if (index < childNodes.GetLowerBound(0) || index > childNodes.GetUpperBound(0)) { throw (new ArgumentOutOfRangeException("index", index, "Array index out of bounds.")); } else if (index < childNodes.GetUpperBound(0)) { Array.Copy(childNodes, index + 1, childNodes, index, childNodes.Length - index - 1); } childNodes.SetValue(null, childNodes.GetUpperBound(0)); } } } // TEST CODE: public static void TestNTree() { NTree topLevel = new NTree(3); NTreeNodeFactory nodeFactory = new NTreeNodeFactory(topLevel); NTreeNodeFactory.NTreeNode one = nodeFactory.CreateNode("One"); NTreeNodeFactory.NTreeNode two = nodeFactory.CreateNode("Two"); NTreeNodeFactory.NTreeNode three = nodeFactory.CreateNode("Three"); NTreeNodeFactory.NTreeNode four = nodeFactory.CreateNode("Four"); NTreeNodeFactory.NTreeNode five = nodeFactory.CreateNode("Five"); NTreeNodeFactory.NTreeNode six = nodeFactory.CreateNode("Six"); NTreeNodeFactory.NTreeNode seven = nodeFactory.CreateNode("Seven"); NTreeNodeFactory.NTreeNode eight = nodeFactory.CreateNode("Eight"); NTreeNodeFactory.NTreeNode nine = nodeFactory.CreateNode("Nine"); topLevel.AddRoot(one); Console.WriteLine("topLevel.GetRoot().CountChildren: " + topLevel.GetRoot().CountChildren()); topLevel.GetRoot().AddNode(two); topLevel.GetRoot().AddNode(three); topLevel.GetRoot().AddNode(four); topLevel.GetRoot().Children[0].AddNode(five); topLevel.GetRoot().Children[0].AddNode(eight); topLevel.GetRoot().Children[0].AddNode(nine); topLevel.GetRoot().Children[1].AddNode(six); topLevel.GetRoot().Children[1].Children[0].AddNode(seven); Console.WriteLine("Display Entire tree:"); topLevel.GetRoot().PrintDepthFirst(); Console.WriteLine("Display tree from node [two]:"); topLevel.GetRoot().Children[0].PrintDepthFirst(); Console.WriteLine("Depth First Search:"); Console.WriteLine("topLevel.DepthFirstSearch(One): " + topLevel.GetRoot().DepthFirstSearch("One").Value().ToString()); Console.WriteLine("topLevel.DepthFirstSearch(Two): " + topLevel.GetRoot().DepthFirstSearch("Two").Value().ToString()); Console.WriteLine("topLevel.DepthFirstSearch(Three): " + topLevel.GetRoot().DepthFirstSearch("Three").Value().ToString()); Console.WriteLine("topLevel.DepthFirstSearch(Four): " + topLevel.GetRoot().DepthFirstSearch("Four").Value().ToString()); Console.WriteLine("topLevel.DepthFirstSearch(Five): " + topLevel.GetRoot().DepthFirstSearch("Five").Value().ToString()); Console.WriteLine("\r\n\r\nBreadth First Search:"); Console.WriteLine("topLevel.BreadthFirstSearch(One): " + topLevel.GetRoot().BreadthFirstSearch("One").Value().ToString()); Console.WriteLine("topLevel.BreadthFirstSearch(Two): " + topLevel.GetRoot().BreadthFirstSearch("Two").Value().ToString()); Console.WriteLine("topLevel.BreadthFirstSearch(Three): " + topLevel.GetRoot().BreadthFirstSearch("Three").Value().ToString()); Console.WriteLine("topLevel.BreadthFirstSearch(Four): " + topLevel.GetRoot().BreadthFirstSearch("Four").Value().ToString()); } [855] top index entry in left column; index entry "wVisual Studio" should be "Visual Studio" (no "w" at beginning)