【问题标题】:Binary Search Tree vs Array for ordered elements有序元素的二叉搜索树与数组
【发布时间】:2016-10-27 19:24:54
【问题描述】:

考虑要插入到数组中的数据始终按顺序排列的场景,即(1, 5, 12, 20, ...)/A[i] >= A[i-1](1000, 900, 20, 1, -2, ...)/A[i] <= A[i-1]

要支持这样的数据集,是二叉搜索树还是数组更高效。

(旁注:我只是想对(K, T, V) 类型的定时哈希映射进行一些简单的分析,时间总是有序的。我正在讨论使用Map<K, BST<T,V>>Map<K, Array<T,V>>。)

据我了解,以下费用(最坏情况)适用——

          Array            BST

Space     O(n)             O(n)
Search    O(log n)         O(n)
Max/Min   O(1)             O(1) *
Insert    O(1) **          O(n)
Delete    O(n)             O(n)

*:最大/最小指针
**:摊销时间复杂度

问:我想更清楚地了解这个问题。对于这两者之间的这种情况,我应该使用什么样的数据结构?请随时讨论其他数据结构,例如自平衡 BST 等。

编辑:

  1. 请注意,我没有考虑平衡二叉搜索树(RBTree 等)的复杂性。如前所述,naive 分析使用二叉搜索树。

  2. 删除已更新为 O(n)(没有考虑时间来搜索节点)。

  3. 倾斜 BST 的最大/最小值将花费 O(n)。但也可以存储MaxMin 的指针,因此总体时间复杂度将为O(1)

【问题讨论】:

  • 请指定如何实现 BST,搜索和插入可以优化到 O(logn),我也怀疑在 O(1) 中重新分级删除。以及您如何在删除后保持最小/最大值。
  • 一个平衡的 BST 也应该是 O(log n) 用于搜索。
  • Insert 在 BST 上应该是 O(log n)。普通数组插入是 O(n);你怎么得到 O(1)?
  • 在 BST 上删除应该是 O(log n)。
  • 我认为因为数据总是按顺序插入,因此数组的 O(1) 而不是 O(n)。但是,在 BST 中的插入仍将保持 O(log n)

标签: algorithm binary-search-tree complexity-theory


【解决方案1】:

请参阅下表,这将帮助您进行选择。请注意,我假设两件事:

1) 数据将始终按排序顺序出现-您提到了这一点,即如果 1000 是最后插入的数据,则新数据将始终超过 1000-如果数据未按排序顺序出现,则插入可能需要 O(log n ),但删除不会改变

2) 您的“数组”实际上类似于 java.util.ArrayList。简而言之,它的长度是可变的。 (比较可变数据结构和不可变数据结构实际上是不公平的)但是,如果它是一个普通数组,则您的删除将采取 amortized O(log n) {O(log n) 搜索和 O(1) 删除,amortized如果你需要创建新数组} 并且插入将需要分期 O(1) {你需要创建新数组}

          ArrayList         BST

 Space     O(n)             O(n)
 Search    O(log n)         O(log n) {optimized from O(n)}
 Max/Min   O(1)             O(log n) {instead of O(1) - you need to traverse till the leaf}
 Insert    O(1)             O(log n) {optimized from O(n)}
 Delete    O(log n)         O(log n)

所以,基于此,ArrayList 似乎更好

【讨论】:

  • 抱歉,我确实提到了O(n) 用于在数组中删除。 O(n) 如果您需要创建新数组但摊销时间复杂度仍然是 O(1) 用于插入。
  • 好的,我想我现在理解得更好了。您正在创建一个由 t 个元素组成的数组,并最初插入 p 个元素,使得 t > p。因此,摊销 O(1)?如果我错了,请纠正我。请在问题中明确提及
  • 所以你通常创建一个大小为k 的数组并插入元素直到可以为止。然后将数组的大小加倍:2k 并插入更多元素。 (在数组中插入新元素的标准做法)。复杂性被摊销的唯一原因O(1) 是因为我们总是知道我们需要在最后一个位置插入。
  • 我知道,这就是为什么我提到 ArrayList 会表现得更好。在一个简单的数组中,您需要存储“lastIndex”,之后所有位置都是无用的(尚未在其中输入的数据),并且您只能得到摊销 O(1) - ArrayList 有效地使用内存并为您提供 O(1)。此外,作为一种标准做法,从不使用数组来存储传入的数据,使用列表或页面
  • 我认为我们都在同一个页面上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多