private AsciiNode BuildAsciiTreeRecursive(TreeNode t) { if (t == null) { return(null); } AsciiNode node = new AsciiNode(); node.left = BuildAsciiTreeRecursive(t.left); node.right = BuildAsciiTreeRecursive(t.right); if (node.left != null) { node.left.parentDir = -1; } if (node.right != null) { node.right.parentDir = 1; } node.label = t.val.ToString(); return(node); }
//This function prints the given level of the given tree, assuming //that the node has the given x cordinate. void PrintLevel(AsciiNode node, int x, int level) { if (node == null) { return; } int isleft = (node.parentDir == -1) ? 1 : 0; if (level == 0) { int i = 0; for (; i < (x - m_printNext - ((node.label.Length - isleft) / 2)); i++) { Console.Write(" "); } m_printNext += i; Console.Write(node.label); m_printNext += node.label.Length; } else if (node.edgeLength >= level) { if (node.left != null) { int i = 0; for (; i < (x - m_printNext - (level)); i++) { Console.Write(" "); } m_printNext += i; Console.Write("/"); m_printNext++; } if (node.right != null) { int i = 0; for (; i < (x - m_printNext + (level)); i++) { Console.Write(" "); } m_printNext += i; Console.Write("\\"); m_printNext++; } } else { PrintLevel(node.left, x - node.edgeLength - 1, level - node.edgeLength - 1); PrintLevel(node.right, x + node.edgeLength + 1, level - node.edgeLength - 1); } }
//Copy the tree into the ascii node structre AsciiNode BuildAsciiTree(TreeNode t) { if (t == null) { return(null); } AsciiNode node = BuildAsciiTreeRecursive(t); node.parentDir = 0; return(node); }
void ComputeRProfile(AsciiNode node, int x, int y) { if (node == null) { return; } int notleft = (node.parentDir != -1) ? 1 : 0; m_rProfile[y] = Math.Max(m_rProfile[y], x + ((node.label.Length - notleft) / 2)); if (node.right != null) { for (int i = 1; i <= node.edgeLength && y + i < MAX_HEIGHT; i++) { m_rProfile[y + i] = Math.Max(m_rProfile[y + i], x + i); } } ComputeRProfile(node.left, x - node.edgeLength - 1, y + node.edgeLength + 1); ComputeRProfile(node.right, x + node.edgeLength + 1, y + node.edgeLength + 1); }
//prints ascii tree for given Tree structure public void PrintAsciiTree(TreeNode t) { if (t == null) { return; } AsciiNode proot = BuildAsciiTree(t); ComputeEdgeLengths(proot); for (int i = 0; i < proot.height && i < MAX_HEIGHT; i++) { m_lProfile[i] = INFINITY_NUM; } ComputeLProfile(proot, 0, 0); int xMin = 0; for (int i = 0; i < proot.height && i < MAX_HEIGHT; i++) { xMin = Math.Min(xMin, m_lProfile[i]); } for (int i = 0; i < proot.height; i++) { m_printNext = 0; PrintLevel(proot, -xMin, i); Console.Write("\n"); } if (proot.height >= MAX_HEIGHT) { Console.Write("(This tree is taller than %d, and may be drawn incorrectly.)\n", MAX_HEIGHT); } }
//This function fills in the edgeLength and //height fields of the specified tree void ComputeEdgeLengths(AsciiNode node) { if (node == null) { return; } ComputeEdgeLengths(node.left); ComputeEdgeLengths(node.right); /* first fill in the edgeLength of node */ if (node.right == null && node.left == null) { node.edgeLength = 0; } else { int hmin = 0; if (node.left != null) { for (int i = 0; i < node.left.height && i < MAX_HEIGHT; i++) { m_rProfile[i] = -INFINITY_NUM; } ComputeRProfile(node.left, 0, 0); hmin = node.left.height; } else { hmin = 0; } if (node.right != null) { for (int i = 0; i < node.right.height && i < MAX_HEIGHT; i++) { m_lProfile[i] = INFINITY_NUM; } ComputeLProfile(node.right, 0, 0); hmin = Math.Min(node.right.height, hmin); } else { hmin = 0; } int delta = 4; for (int i = 0; i < hmin; i++) { delta = Math.Max(delta, GAP + 1 + m_rProfile[i] - m_lProfile[i]); } //If the node has two children of height 1, then we allow the //two leaves to be within 1, instead of 2 if (((node.left != null && node.left.height == 1) || (node.right != null && node.right.height == 1)) && delta > 4) { delta--; } node.edgeLength = ((delta + 1) / 2) - 1; } //now fill in the height of node int h = 1; if (node.left != null) { h = Math.Max(node.left.height + node.edgeLength + 1, h); } if (node.right != null) { h = Math.Max(node.right.height + node.edgeLength + 1, h); } node.height = h; }