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

Algorithm 如何在O(N)时间内建立二叉树?,algorithm,Algorithm,继上一个问题之后,我很想知道如何从N个未排序的大整数数组按N个时间顺序构建二叉树?除非列表中有一些先决条件允许您在固定时间内计算每个项在树中的位置,否则不可能“构建”,即顺序插入,在O(N)时间内将项目放入树中。每次插入都必须比较多达对数M次,其中M是树中已存在的项目数。除非列表中有一些先决条件允许您在固定时间内计算每个项目在树中的位置,否则无法“构建”,即在O(N)时间内顺序插入项目到树中。每次插入都必须比较多达对数M次,其中M是树中已存在的项目数。我同意这在一般情况下似乎是不可能的(假设我们

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

除非列表中有一些先决条件允许您在固定时间内计算每个项在树中的位置,否则不可能“构建”,即顺序插入,在O(N)时间内将项目放入树中。每次插入都必须比较多达对数M次,其中M是树中已存在的项目数。

除非列表中有一些先决条件允许您在固定时间内计算每个项目在树中的位置,否则无法“构建”,即在O(N)时间内顺序插入项目到树中。每次插入都必须比较多达对数M次,其中M是树中已存在的项目数。

我同意这在一般情况下似乎是不可能的(假设我们有一个由N个项目组成的通用、完全有序的集合)。下面是一个非正式的论点,我基本上将在S上构建BST简化为排序S的问题

非正式辩论。设我们是一组N个元素。现在构造一个二进制搜索树T,它在O(N)时间内存储来自S的项

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


如果| T |=o(N logn),那么你只需要在o(N logn)时间内解决了一般排序问题,这是一个矛盾。

我同意这在一般情况下似乎是不可能的(假设我们有一个由N项组成的一般的、完全有序的集合)。下面是一个非正式的论点,我基本上将在S上构建BST简化为排序S的问题

非正式辩论。设我们是一组N个元素。现在构造一个二进制搜索树T,它在O(N)时间内存储来自S的项

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


如果| T |=o(N logn),那么您只需在o(N logn)时间内解决一般排序问题,这是一个矛盾。

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

使用RadixSort对数组进行排序,这是O(N)。然后,使用递归过程插入到leaf中,如:

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;
}
节点*插入(int*数组,int大小){
如果(大小数据=数组[中点];
rc->left=插入(数组,中点);
rc->right=insert(数组+中点+1,大小-中点-1);
返回rc;
}

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

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

使用RadixSort对数组进行排序,这是O(N)。然后,使用递归过程插入到Leaf中,如:

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;
}
节点*插入(int*数组,int大小){
如果(大小数据=数组[中点];
rc->left=插入(数组,中点);
rc->right=insert(数组+中点+1,大小-中点-1);
返回rc;
}

因为我们不从上到下迭代树,而是总是将节点附加到当前的叶子上,这也是O(1).

好的,只是为了完整性…所讨论的二叉树是从一个数组中构建的,每个数组元素都有一个叶子。它将它们保持在原始的索引顺序,而不是值顺序,因此它不会神奇地让你在线性时间内对列表排序。它还需要平衡

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


好的,只是为了完整性…所讨论的二叉树是从一个数组中构建的,每个数组元素都有一个叶子。它将它们保持在原始的索引顺序,而不是值顺序,因此它不会神奇地让你在线性时间内对列表排序。它还需要平衡

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


据我所知,这是不可能的,因为这意味着你可以在O(n)时间内对列表进行排序。@MarcB单击链接以获取上下文。@Willem Van Onsem,这是我的想法,但我不是说这无法完成,而是随时准备倾听和学习;)但链接上说“当你已经知道排序时,如何在O(n)时间内构建树”。这不同于从未排序的整数中构建一个。您可以使用桶排序或计数排序对k个可能的变体中的n个项进行O(n+k)排序。还使用O(k)空间,这可能非常昂贵(因此我在上述问题中添加了大整数)据我所知,这是不可能的,因为这意味着你可以在O(n)时间内对列表进行排序。@MarcB单击链接获取上下文。@Willem Van Onsem,这是我的想法,但我不是说这不可能,而是随时准备倾听和学习;)但链接上说“当你已经知道排序时,如何在O(n)时间内构建树”。这不同于从未排序的整数中构建一个。您可以使用桶排序或计数排序对k个可能变化中的n个项目进行O(n+k)排序。还使用O(k)空间,这可能会非常昂贵(因此我在上面的问题中添加了大整数),这一直是我的理解,因此这个问题。也就是说,仅仅因为我们没有看到该算法并不意味着它不存在。二叉搜索树是计算机科学中研究最多的主题之一。它们建立在通过比较进行排序的原则之上。已经证明,BST最快的基于比较的插入是O(logn)。要获得更快的速度,您需要在数据集中预先存在一些结构。例如,如果您知道您的数据集已经排序,您可以想出一种更快的方法来构建树。@user2313300 true,但这是错误的