如何在O(N)时间内构建二叉树?

时间:2016-03-07 19:18:03

标签: algorithm

继上一个问题here后,我很想知道如何按N次排序从N个未排序的大整数数组构建二叉树?

4 个答案:

答案 0 :(得分:2)

除非您在列表中有一些前提条件允许您在常量时间内为每个项目计算树中的位置,否则无法“构建”,即将项目顺序插入到O中的树中( N)时间。每次插入必须比较Log M次,其中M是树中已有的项目数。

答案 1 :(得分:1)

我同意这似乎是不可能的(假设我们有 N 项的一般的,完全有序的 S 。)以下是一个非正式的论证,我基本上减少了在 S 上构建BST以解决 S 的排序问题。

非正式参数。 S 成为一组 N 元素。现在构建一个二进制搜索树 T ,用于在 O(N)时间内存储来自 S 的项目。

现在进行树的顺序遍历并在访问时打印树叶的值。您基本上对 S 中的元素进行了排序。这需要 O(| T |)步骤,其中 | T | 是树的大小(即节点数)。 (在最坏的情况下,BST的大小是 O(N log N)。)

如果 | T | = o(N log N)那么你刚刚解决了 o(N log N)时间中的一般排序问题,这是一个矛盾。< / p>

答案 2 :(得分:1)

好的,只是为了完整性......所讨论的二叉树是从数组构建的,并且每个数组元素都有一个叶子。它使它们保持原始的索引顺序,非值顺序,因此它不会让您在线性时间内对列表进行排序。它也需要平衡。

要在线性时间内构建这样的树,可以使用这样的简单递归算法(使用基于0的索引):

//build a tree of elements [start, end) in array
//precondition: end > start
buildTree(int[] array, int start, int end)
{
    if (end-start > 1)
    {
        int mid = (start+end)>>1;
        left = buildTree(array, start, mid);
        right = buildTree(array, mid, end);
        return new InternalNode(left,right); 
    }
    else
    {
        return new LeafNode(array[start]);
    }
}

答案 3 :(得分:0)

我有一个想法,它是如何可能的。

使用RadixSort对数组进行排序,这是O(N)。此后,使用递归过程插入叶子,如:

node *insert(int *array, int size) {
  if(size <= 0)
     return NULL;
  node *rc = new node;
  int midpoint = size / 2;
  rc->data = array[midpoint];
  rc->left  = insert(array, midpoint);
  rc->right = insert(array + midpoint + 1, size - midpoint - 1);
  return rc;
}

由于我们不从上到下迭代树,但总是将节点附加到当前叶子,这也是O(1)。