如何在C#中打印出树形结构?

时间:2019-03-26 16:10:44

标签: c#

我想以非递归的顺序打印非二叉树结构。 我有以下代码- 我想在代码遇到根元素的子代和子代时增加计数。

public static void PrintTree(Node tree)
{
    List<Node> firstStack = new List<Node>();
    firstStack.Add(tree);

    List<List<Node>> childListStack = new List<List<Node>>();
    childListStack.Add(firstStack);

    while (childListStack.Count > 0)
    {
        List<Node> childStack = childListStack[childListStack.Count - 1];

        if (childStack.Count == 0)
        {
            childListStack.RemoveAt(childListStack.Count - 1);
        }
        else
        {
            tree = childStack[0];
            childStack.RemoveAt(0);

            string indent = "";
            for (int i = 0; i < childListStack.Count - 1; i++)
            {
                indent += (childListStack[i].Count > 0) ? "|  " : "   ";
            }

            Console.WriteLine(indent + "+- " + tree.Name);

            if (tree.Children.Count > 0)
            {
                childListStack.Add(new List<Node>(tree.Children));
            }
        }
    }
}

我得到的输出是-

+- root
   +- branch-A
   |  +- sibling-X
   |  |  +- grandchild-A
   |  |  +- grandchild-B
   |  +- sibling-Y
   |  |  +- grandchild-C
   |  |  +- grandchild-D
   |  +- sibling-Z
   |     +- grandchild-E
   |     +- grandchild-F
   +- branch-B
      +- sibling-J
      +- sibling-K

我需要的输出是-

1 branch-A
2 sibling-X
3 grandchild-A
3 grandchild-B
2 sibling-Y
3 grandchild-C
3 grandchild-D
2 sibling-Z
3 grandchild-E
3 grandchild-F
1 branch-B
2 sibling-J
2 sibling-K

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

这种遍历类型称为深度优先遍历。这里的想法是尽可能深入直到到达叶节点。然后,对所有未开发的节点的其余子节点重复该过程。

但是,使用Stack实际上很容易实现。现在,为了知道当前的级别,您需要跟踪每个节点级别(这是因为到达叶子之后,您必须返回到与当前节点共享最小祖先数量的下一个节点,并且由于需要打印的下一个节点可以等于或小于上一个节点的任何级别,因此除非跟踪它们,否则您将无法知道。

您可以通过以下方式进行操作:

        public static void PrintTree2(Node tree)
        {
            Stack<Node> stack = new Stack<Node>();
            Stack<int> nodeLevel = new Stack<int>();
            stack.Push(tree);
            nodeLevel.Push(1);

            while (stack.Count > 0)
            {
                Node next = stack.Pop();
                int curLevel = nodeLevel.Pop();
                Console.WriteLine(curLevel + " " + next.Name);

                foreach (Node c in next.Children)
                {
                    nodeLevel.Push(curLevel + 1);
                    stack.Push(c);
                }
            }
        }

答案 1 :(得分:0)

嗯,这看起来很熟悉 :wink:

原算法为了避免函数调用栈溢出,保留了一堆子列表。有了它,您可以通过检查 childListStack 的当前长度(并删除与 indent 字符串有关的所有内容)来获取给定节点的深度。

无递归

public static void PrintTree(Node tree)
{
    List<Node> firstStack = new List<Node>();
    firstStack.Add(tree);

    List<List<Node>> childListStack = new List<List<Node>>();
    childListStack.Add(firstStack);

    while (childListStack.Count > 0)
    {
        List<Node> childStack = childListStack[childListStack.Count - 1];

        if (childStack.Count == 0)
        {
            childListStack.RemoveAt(childListStack.Count - 1);
        }
        else
        {
            tree = childStack[0];
            childStack.RemoveAt(0);

            Console.WriteLine((childListStack.Count - 1) + " " + tree.Name);

            if (tree.Children.Count > 0)
            {
                childListStack.Add(new List<Node>(tree.Children));
            }
        }
    }
}

这将输出:

0 root
1 branch-A
2 sibling-X
3 grandchild-A
3 grandchild-B
2 sibling-Y
3 grandchild-C
3 grandchild-D
2 sibling-Z
3 grandchild-E
3 grandchild-F
1 branch-B
2 sibling-J
2 sibling-K

带递归

也就是说,使用经典递归解决这个问题要简单得多。只需要在遍历子节点时增加深度即可,输出相同的结果。

public static void PrintTree(Node tree, int depth = 0)
{
    Console.WriteLine(depth + " " + tree.Name);

    for (int i = 0; i < tree.Children.Count; i++)
    {
        PrintTree(tree.Children[i], depth + 1);
    }
}