二分搜索与二分搜索树
与使用二分搜索的排序数组相比,二分搜索树有什么好处?仅通过数学分析,我没有看到差异,因此我认为低级实现开销一定存在差异。平均案例运行时间的分析如下所示。
使用二分查找排序数组
搜索:O(log(n))
插入:O(log(n))(我们运行二分搜索来查找插入元素的位置)
删除:O(log(n))(我们运行二分搜索来查找要删除的元素)
二叉搜索树
搜索:O(log(n))
插入:O(log(n))
删除:O(log(n))
对于上面列出的操作,二叉搜索树的最坏情况是 O(n)(如果树不平衡),因此这看起来实际上比二分搜索的排序数组更糟糕。
另外,我并不是假设我们必须事先对数组进行排序(这将花费 O(nlog(n))),我们会将元素一一插入到数组中,就像我们对二叉树所做的那样。唯一的好处我可以看到 BST 的特点是它支持其他类型的遍历,如中序、前序、后序。
What is the benefit of a binary search tree over a sorted array with binary search? Just with mathematical analysis I do not see a difference, so I assume there must be a difference in the low-level implementation overhead. Analysis of average case run time is shown below.
Sorted array with binary search
search: O(log(n))
insertion: O(log(n)) (we run binary search to find where to insert the element)
deletion: O(log(n)) (we run binary search to find the element to delete)
Binary search tree
search: O(log(n))
insertion: O(log(n))
deletion: O(log(n))
Binary search trees have a worst case of O(n) for operations listed above (if tree is not balanced), so this seems like it would actually be worse than sorted array with binary search.
Also, I am not assuming that we have to sort the array beforehand (which would cost O(nlog(n)), we would insert elements one by one into the array, just as we would do for the binary tree. The only benefit of BST I can see is that it supports other types of traversals like inorder, preorder, postorder.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的分析是错误的,对于排序数组来说,插入和删除都是 O(n),因为您必须物理地移动数据来为插入腾出空间或压缩它以覆盖已删除的项目。
哦,完全不平衡二叉搜索树的最坏情况是 O(n),而不是 O(logn)。
Your analysis is wrong, both insertion and deletion is O(n) for a sorted array, because you have to physically move the data to make space for the insertion or compress it to cover up the deleted item.
Oh and the worst case for completely unbalanced binary search trees is O(n), not O(logn).
查询任何一个都没有多大好处。查询。
但是,当您一次添加一个元素时,构造一棵排序树比构造一个排序数组要快得多。因此,完成后将其转换为数组是没有意义的。
There's not much of a benefit in querying either one.
But constructing a sorted tree is a lot faster than constructing a sorted array, when you're adding elements one at a time. So there's no point in converting it to an array when you're done.
另请注意,有用于维护平衡二叉搜索树的标准算法。他们消除了二叉树的缺陷并保留了所有其他优点。不过,它们很复杂,因此您应该首先了解二叉树。
除此之外,大 O 可能是相同的,但常数并不总是相同。使用二叉树,如果正确存储数据,则可以很好地利用多个级别的缓存。结果是,如果您正在进行大量查询,大部分工作都会保留在 CPU 缓存中,这会大大加快速度。如果您小心地构建树,则尤其如此。请参阅 http://blogs。 msdn.com/b/devdev/archive/2007/06/12/cache-oblivious-data-structs.aspx 示例展示了巧妙的树布局如何极大地提高性能。您执行二分搜索的数组不允许使用任何此类技巧。
Note also that there are standard algorithms for maintaining balanced binary search trees. They get rid of the deficiencies in binary trees and maintain all of the other strengths. They are complicated, though, so you should learn about binary trees first.
Beyond that, the big-O may be the same, but the constants aren't always. With binary trees if you store the data correctly, you can get very good use of caching at multiple levels. The result is that if you are doing a lot of querying, most of your work stays inside of CPU cache which greatly speeds things up. This is particularly true if you are careful in how you structure your tree. See http://blogs.msdn.com/b/devdev/archive/2007/06/12/cache-oblivious-data-structures.aspx for an example of how clever layout of the tree can improve performance greatly. An array that you do a binary search of does not permit any such tricks to be used.
添加到@Blindy,我会说排序数组中的插入比CPU指令O(logn)需要更多的内存操作O(n)
std::rotate()
,请参阅插入排序。我猜 左子右兄弟树结合了二叉树和排序数组的本质。
std::rotate() 进行插入排序
std::rotate()
std::vector::erase()
Adding to @Blindy , I would say the insertion in sorted array takes more of memory operation O(n)
std::rotate()
than CPU instruction O(logn), refer to insertion sort.I guess Left child right sibling tree combines the essence of binary tree and sorted array.
std::rotate()
std::vector::erase()
std::rotate()
when inserting on left child if kept unbalancedstd::vector::erase()