使用O(1)空间以BFS方式打印二叉树

时间:2011-11-07 16:06:41

标签: algorithm data-structures

我想知道是否可以在仅使用O(1)空间的情况下以广度优先打印二叉树?

困难的部分是必须使用额外的空间来记忆下一个级别来遍历,并且随着n的增长而增长。

由于我们没有对时间部分施加任何限制,可能会有一些效率低下(在时间上)的方法可以达到这个目的吗?

有什么想法吗?

4 个答案:

答案 0 :(得分:4)

这取决于一些更精细的定义,例如,如果边有后向链接。然后它很容易,因为你可以按照树上的后退链接。否则,如果没有O(lg 节点数)空间,我就无法想办法,因为你需要至少记住“上面”的节点。

<强>更新

哦等等,当然可以在O(1) space 中进行空格时间交易。在任何地方你都想做一个反向链接,你保存你的位置并做BFS,跟踪最近的节点,直到你找到你的。然后返回到最近访问过的节点并继续。

问题是,那是O(1)空间但是O(n ^ 2)时间。

另一次更新

假设我们已经到达节点n_i,并且我们想要到达该节点的父节点,我们将其称为wlg n_j。我们已经确定了区分根节点n_0。

修改先呼吸搜索算法,以便当它跟随有向边(n_x,n_y)时,存储传出或“传入”节点。因此,当您关注(n_x,n_y)时,您将保存n_x。

当您从n_0再次启动BFS时,可以保证(假设它确实是一棵树),在某些时候,您将转换边缘(n_j,n_i)。那时你会发现你回到了n_i。你已经存储了n_j,所以你知道反向边是(n_i,n_j)。

因此,只有两个额外的单元格可以获得单个回溯,一个用于n_0,另一个用于“已保存”节点。这是O(1)

我不太确定O(n ^ 2) - 已经很晚了,这是艰难的一天,所以我不想撰写证据。我确定它是O((| N | + | E |)^ 2)其中| N |和| E |是顶点和边集的大小。

答案 1 :(得分:1)

我知道这绝对不是问题的答案,但是可以使用O( d )空间以广度优先的顺序访问树的节点,其中 d 是树的深度,由递归iterative deepening depth first search(IDDFS)组成。当然,堆栈需要空间。在平衡树的情况下, d = O(lg n )其中 n 是节点数。老实说,如果没有@Charlie Martin建议的反向链接,你不会在恒定的空间里看到它。

答案 2 :(得分:1)

一个有趣的特例是堆。

来自heapq docs

  

堆是二进制树,每个父节点的值都小于   超过或等于任何一个孩子。此实现使用数组   对于所有k,heap[k] <= heap[2*k+1]heap[k] <= heap[2*k+2],   从零开始计算元素。为了比较,不存在   元素被认为是无限的。一个有趣的属性   heap是它的最小元素始终是根heap[0]。 [FrançoisPinard的解释]

如何在内存中表示树(数组的索引):

                               0

              1                                 2

      3               4                5               6

  7       8       9       10      11      12      13      14

15 16   17 18   19 20   21 22   23 24   25 26   27 28   29 30

在这种情况下,数组中的节点已经以广度第一顺序存储。

for value in the_heap:
    print(value)

O(1)在太空中。

答案 3 :(得分:0)

很容易实现一种递归方法,以在给定级别获得树的所有节点。因此,我们可以计算树的高度并获得所有节点和每个级别。这是树的Level Order Traversal。但是,时间复杂度为O(n^2)。以下是Java实现(source)。

class Node 
{ 
    int data; 
    Node left, right; 
    public Node(int item) 
    { 
        data = item; 
        left = right = null; 
    } 
} 

class BinaryTree 
{ 
    Node root; 

    public BinaryTree() 
    { 
        root = null; 
    } 

    void PrintLevelOrder() 
    { 
        int h = height(root); 
        int i; 
        for (i=1; i<=h; i++) 
            printGivenLevel(root, i); 
    } 

    int Height(Node root) 
    { 
        if (root == null) 
           return 0; 
        else
        { 
            int lheight = height(root.left); 
            int rheight = height(root.right); 

        } 
    } 

    void PrintGivenLevel (Node root ,int level) 
    { 
        if (root == null) 
            return; 
        if (level == 1) 
            System.out.print(root.data + " "); 
        else if (level > 1) 
        { 
            printGivenLevel(root.left, level-1); 
            printGivenLevel(root.right, level-1); 
        } 
    }
}