【问题标题】:How to print a binary tree level by level? Interview question!如何逐级打印二叉树?面试题!
【发布时间】:2011-04-06 13:26:04
【问题描述】:

如何逐级打印二叉树?

这是我今天收到的一个面试问题。果然,使用 BFS 风格肯定会奏效。但是,后续问题是:如何使用常量内存打印树? (所以不能使用队列)

我想过以某种方式将二叉树转换为链表,但没有想出具体的解决方案。

有什么建议吗?

谢谢

【问题讨论】:

  • 我不确定,但我们不能修改节点的结构以包含关卡信息吗?而且,因此通过任何遍历,我们都可以使用适当的级别初始化所有节点,并且通过另一次遍历,也许可以打印所有节点及其级别编号?

标签: algorithm binary-tree


【解决方案1】:

避免使用额外内存(无论如何要多得多)的一种方法是在遍历树时对其进行操作 - 当您向下遍历节点时,将其指针复制到其中一个子节点,然后将其反转指向父级。当您到达底部时,您可以按照链接返回到父级,并在前进时将它们反转以指向子级。

当然,这不是全部工作,但它可能是单个“最棘手”的部分。

【讨论】:

  • 逐级打印树为什么要往上遍历?
  • 因为没有直接指向一个节点的兄弟节点的链接,所以必须先通过父节点。
  • 谢谢我明白了。似乎可行,但我必须先找出一个具体的算法。
  • @Codier:正如 Dave Rager 指出的那样,您需要这样做。您还(通常)希望打印以其后代为中心的根,在这种情况下,您需要知道有多少后代将在其左侧结束。
  • @MAK: 通常 用于节点指向其子节点的指针(无论您目前正在使用哪个子节点)。这是旧技巧的变体,通过反转每个节点的链接,指向其前身而不是其后继者(然后在您回到开头时将其切换回来),向前遍历链表然后回到开头。
【解决方案2】:

扩展 Jerry Coffin 所说的内容,我之前曾问过一个关于使用中序遍历做类似事情的问题。它使用与他解释的相同的逻辑。

在这里查看:

Explain Morris inorder tree traversal without using stacks or recursion

【讨论】:

    【解决方案3】:

    您可以通过重复地按顺序遍历树,同时只打印指定级别的那些节点来做到这一点。但是,这不是严格的常量内存,因为递归使用调用堆栈。而且效率超级低。比如 O(n * 2^n) 什么的。

    printLevel = 1;
    
    while(moreLevels) {
    
        moreLevels = printLevel(root, 1, printLevel);
        printLevel++;
    }
    
    boolean printLevel(Node node, int currentLevel, int printLevel) {
    
        boolean moreLevels = false;
    
        if(node == null) {
            return(false);
        }
    
        else if(currentLevel == printLevel) {
            print the node value;
        }
    
        else {
    
            moreLevels |= printLevel(node.leftChild, currentLevel + 1, printLevel);
            moreLevels |= printLevel(node.rightChild, currentLevel + 1, printLevel);
        }
    
        return(moreLevels);
    }
    

    【讨论】:

    • 这个问题可以在调用堆栈上没有log(n)额外内存的情况下解决,但是有点棘手。 (另外,如果你要使用递归,有一个非常简单的算法比这更快)
    • 如果树完全平衡,这实际上只处理2n 节点。还不错。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多