【问题标题】:Get median from AVL tree?从 AVL 树中获取中位数?
【发布时间】:2021-09-16 05:01:08
【问题描述】:

如果您有一棵 AVL 树,从中获取中位数的最佳方法是什么?中位数将被定义为排序列表中索引为 ceil(n/2)(索引从 1 开始)的元素。

如果列表是

1 3 5 7 8

中位数是 5。如果列表是

1 3 5 7 8 10

中位数是 5。

如果可以扩充树,我认为最好让每个节点都知道子树的大小(节点数),(即 1 + left.size + right.size)。使用这个,我能想到的最好的方法是使中位数搜索 O(lg n) 时间,因为您可以通过比较索引来遍历。

有没有更好的办法?

【问题讨论】:

  • FWIW,将计数放入节点的技术使您的 AVL 树也可以放入顺序统计树:en.wikipedia.org/wiki/Order_statistic_tree。当然,您还必须修改平衡算法中的旋转以调整节点数。 @templatetypedef 对树进行线程化并使用单个中值指针的想法是最佳的。它不需要节点计数,并且每个操作的时间是恒定的。他没有提到您还需要知道树中的总节点数,以便您可以确定中位数是单个元素(奇数节点数)还是两个的平均值(偶数节点数)。
  • @Gene 感谢您填写这些详细信息!

标签: performance algorithm data-structures median avl-tree


【解决方案1】:

如果您需要优化中值查询,则增强 AVL 树以存储子树大小通常是这里的最佳方法。它需要时间 O(log n),非常快。

如果您要计算中位数很多次,您可能会使用增广树并缓存中位数,以便您可以在 O(1) 时间内读取它。每次进行插入或删除时,您可能需要重新计算时间中值 O(log n),这会稍微减慢速度,但不会影响渐近成本。

另一种选择是通过树中的节点创建一个双向链表,以便您可以在恒定时间内从一个节点导航到其后继或前任。如果你这样做,那么你可以存储一个指向中间元素的指针,然后在插入或删除时,根据需要将指针向左或向右移动。如果您删除中位数本身,您可以随意向左或向右移动指针。这不需要任何扩充并且可能会更快一些,但它会在每个节点中添加两个额外的指针。

希望这会有所帮助!

【讨论】:

  • 我很想看看在 Javascript 中使用指针的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多