我想知道是否有合适的算法来维护二叉树的平衡,当知道元素总是按顺序插入时。
这样做的一个选择是使用从排序数组或链表创建平衡树的标准方法,如this问题和this其他问题中所述。但是,我想要一种方法,可以将一些元素插入到树中,然后对其执行查找,然后添加其他元素,而不必将树分解为列表并重新制作整个事物。
另一种选择是使用许多自平衡树实现中的一种,AVL,AA,Red-Black等等。但是,所有这些都在插入过程中施加了某种开销,而我是想知道是否有办法避免这种情况,因为元素始终按递增顺序插入。
因此,为了清楚起见,我想知道是否有一种方法可以维护一个平衡的二叉树,这样我就可以在任何点插入一个任意的新元素并保持树的平衡,提供新元素在树的排序中比树中已存在的所有元素更大。
举个例子,假设我有以下树:
4
/ \
/ \
2 6
/ \ / \
1 3 5 7
如果我知道元素大于7,是否有一种简单的方法可以在插入新元素时保持平衡?
答案 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出现在我的脑海中。由于总是插入大于集合中已有元素的元素,因此更新指针应该非常容易。