当元素按顺序插入时保持二叉树平衡

时间:2011-10-30 15:19:20

标签: algorithm tree binary-tree

我想知道是否有合适的算法来维护二叉树的平衡,当知道元素总是按顺序插入时。

这样做的一个选择是使用从排序数组或链表创建平衡树的标准方法,如this问题和this其他问题中所述。但是,我想要一种方法,可以将一些元素插入到树中,然后对其执行查找,然后添加其他元素,而不必将树分解为列表并重新制作整个事物。

另一种选择是使用许多自平衡树实现中的一种,AVL,AA,Red-Black等等。但是,所有这些都在插入过程中施加了某种开销,而我是想知道是否有办法避免这种情况,因为元素始终按递增顺序插入。

因此,为了清楚起见,我想知道是否有一种方法可以维护一个平衡的二叉树,这样我就可以在任何点插入一个任意的新元素并保持树的平衡,提供新元素在树的排序中比树中已存在的所有元素更大。

举个例子,假设我有以下树:

       4
      / \
     /   \
    2     6
   / \   / \
  1   3 5   7

如果我知道元素大于7,是否有一种简单的方法可以在插入新元素时保持平衡?

3 个答案:

答案 0 :(得分:6)

如果你真的对使用BST感兴趣(我认为这不是最好的选择,你可以在我的其他答案中阅读),你可以这样做:

有正常的BST。这意味着如果我们设法在插入期间保持深度,则查找为O(log N)。

进行插入时(假设我们的元素大于之前的元素),您可以从根到最右边的元素。当您遇到其子树是完美二叉树的节点(所有内部节点都有2个子节点且所有叶子处于相同深度)时,您将新节点作为此节点的父节点插入。

如果您到达树中最右侧的节点而您没有应用之前的规则,则表示它有一个左子节点,但它没有正确的节点。因此,新节点成为当前节点的正确子节点。

例如,在下面的第一个树中,4的子树不是完美的,但5的子树是(根据定义,只有一个节点的树是完美的)。因此,我们将6添加为5的父级,这意味着4是6的父级,5是6的左子级。

如果我们尝试添加另一个节点,那么4的子树仍然不完美,也不是6的子树.6是最右边的节点,所以我们将7添加为6的右子节点。 / p>

     4             4             4
    / \           / \           / \
   /   \         /   \         /   \
  2     5 -->   2     6 -->   2     6
 / \           / \   /       / \   / \
1   3         1   3 5       1   3 5   7

如果我们使用这个算法,根的左子树的子树将永远是完美的,并且右子的子树将永远不会具有比左子的更高的高度。因此,整个树的高度始终为O(log N),因此查找时间也是如此。插入也将花费O(log N)时间。

与自平衡BST相比,时间复杂度相同。但是这个算法应该更容易实现,实际上可能比它们更快。

与我的其他答案中基于阵列的解决方案相比,查找的时间复杂度相同,但此BST的插入时间更短。

答案 1 :(得分:3)

根据您描述的要求,您根本不需要树。您只需要排序dynamic array

插入时,始终插入(O(1)摊销)。

搜索时,请使用普通binary search(O(log N))。

这假设您不需要任何其他操作,或者您不介意它们将是O(N)。

答案 2 :(得分:0)

我认为你先验地知道元素的顺序递增。此外,我想你想要一棵树来快速搜索特定的元素。

我不确定二进制树是否最适合您描述的快速插入。但是可能还有其他数据结构可以很好地处理您描述的用例:尽管我从未使用它,但skip-list出现在我的脑海中。由于总是插入大于集合中已有元素的元素,因此更新指针应该非常容易。