我正在寻找一种数据结构,它至少可以确保删除和插入节点的 Log(n) 复杂性以及接近 O(1) 或摊销 Log(n) 的东西来搜索最大值(或最小值)。
我正在考虑使用经过修改的自平衡 BST(哪个?)来记住插入的最大值(或最小值)。
有什么建议吗?
抱歉,我必须编辑问题……当然,自平衡 BST 可以允许在 log(n) 中搜索 max 和 min,但我正在考虑更多关于 O(1) 的东西。
我正在寻找一种数据结构,它至少可以确保删除和插入节点的 Log(n) 复杂性以及接近 O(1) 或摊销 Log(n) 的东西来搜索最大值(或最小值)。
我正在考虑使用经过修改的自平衡 BST(哪个?)来记住插入的最大值(或最小值)。
有什么建议吗?
抱歉,我必须编辑问题……当然,自平衡 BST 可以允许在 log(n) 中搜索 max 和 min,但我正在考虑更多关于 O(1) 的东西。
您可以使用几乎任何自平衡 BST(例如红黑、AVL)。
如果您跟踪最小值和最大值,则获取它们的查询将花费 O(1)。
由于最小值和最大值只能在插入和删除时改变,因此您基本上可以在执行这些操作时重新确定它(在 O(log n) 中)(它们的运行时间仍然是 O(log n))。
尽管在收到查询时重新确定最小值或最大值可能是一个更好的主意,并且自上次查询以来存在插入或删除。
也有可能对此更加聪明——如果你到目前为止只向左走,那么你就处于最低限度,如果你只是向右走,那么你就处于最高水平。插入时,只需在适当的情况下替换最小值/最大值。删除时,只需从已删除节点开始在树中四处寻找新的最小值/最大值。
AVL 适合:搜索 max 和 min 是 O(log n),因为 min 是最左边的节点,而 max 是最右边的节点,并且树是平衡的。如果您只删除最大/最小节点,这也是 O(log n) 但只有在删除节点时才会使树不平衡。
评论已经讨论了双端堆,并得出结论认为它不适合,因为删除需要知道元素的位置。我相信这可以在许多情况下以合理的成本解决,如下所示:维护两个双端堆,一个(比如 A)条目进入集合,一个(比如 B)条目被删除。
这将为您提供 O(log(k)) 插入和删除,并摊销 O(1) 最小/最大计算。但是,在这种情况下,k 是插入到集合中但尚未从 A 和 B 中弹出的元素数;更明显的其他解决方案具有复杂性,具体取决于集合中实际元素的数量(即,已插入但尚未删除的元素) - 我们称这个数字为 n。您可能会想出 k 远大于 n 以至于这与其他解决方案没有竞争力的场景 - 以及 k 和 n 大致相等且此解决方案更快的其他场景。因此,这是否是一个好主意取决于您的应用程序。