/// <summary> /// Returns the number of references to the node represented by 'nodeIndex'. The count will max out at 255 (but not wrap) /// </summary> public byte RefCount(NodeIndex nodeIndex) { if (m_refCounts == null) { // Do the expensive operation of walking the graph collecting refcounts. m_refCounts = new byte[(int)m_graph.NodeIndexLimit]; m_refCounts[(int)m_graph.RootIndex] = 1; var nodeStorage = m_graph.AllocNodeStorage(); // Need for enumeration below. var nodesToVisit = new Queue <NodeIndex>(1000); nodesToVisit.Enqueue(m_graph.RootIndex); while (nodesToVisit.Count > 0) { var curNodeIndex = nodesToVisit.Dequeue(); var curNode = m_graph.GetNode(curNodeIndex, nodeStorage); for (var childIndex = curNode.GetFirstChildIndex(); childIndex != NodeIndex.Invalid; childIndex = curNode.GetNextChildIndex()) { byte val = m_refCounts[(int)childIndex]; if (val == 0) { nodesToVisit.Enqueue(childIndex); } val++; if (val == 0) { val = 255; // increment, but never wrap-around. } m_refCounts[(int)childIndex] = val; } } var singletons = 0; var orphans = 0; var max = 0; var totalRefs = 0.0; foreach (var refCount in m_refCounts) { totalRefs += refCount; if (refCount == 1) { singletons++; } else if (refCount == 0) { orphans++; } else if (refCount == 255) { max++; } } Trace.WriteLine("Total = " + m_refCounts.Length); Trace.WriteLine("Singletons = " + singletons); Trace.WriteLine("Orphans = " + orphans); Trace.WriteLine("Max = " + max); Trace.WriteLine("Average = " + (totalRefs / m_refCounts.Length).ToString("f2")); Trace.WriteLine(""); } return(m_refCounts[(int)nodeIndex]); }