我可以看出,在二叉搜索树中查找值时,每次将树的一半与我们正在寻找的值进行比较。
但是,我不明白为什么时间复杂度是O(log(n))
。因此,我的问题是:
如果我们有一个包含N个元素的树,查找并检查特定值是否存在的时间复杂度为O(log(n)),如何得出这个结果?
我可以看出,在二叉搜索树中查找值时,每次将树的一半与我们正在寻找的值进行比较。
但是,我不明白为什么时间复杂度是O(log(n))
。因此,我的问题是:
如果我们有一个包含N个元素的树,查找并检查特定值是否存在的时间复杂度为O(log(n)),如何得出这个结果?
对我来说最简单的方法是查看log2(n)的图表,其中n是二叉树中节点的数量。以表格的形式呈现如下:
对我而言,最简单的方法是查看 log2(n) 的图表,其中 n 是二叉树中的节点数。这个表格看起来像:
log2(n) = d
log2(1) = 0
log2(2) = 1
log2(4) = 2
log2(8) = 3
log2(16)= 4
log2(32)= 5
log2(64)= 6
然后我画了一棵小的二叉树,它从深度d=0到d=3:
d=0 O
/ \
d=1 R B
/\ /\
d=2 R B R B
/\ /\ /\ /\
d=3 R B RB RB R B
当树中节点的数量n有效地翻倍时(例如,当深度d从d=2增加到d=3时,n从7增加到15(这几乎是一倍),增加1)所需的处理量(或时间)仅增加了1个额外的计算(或迭代),因为处理量与d有关。
我们可以看到,我们只需在深度d下降1级,从d=2降至d=3,即可找到我们想要的节点,而节点数翻倍了。这是因为我们现在搜索了整棵树,至少我们需要搜索一半才能找到我们想要的节点。
我们可以将其写成d = log2(n)
,其中d告诉我们在树中有n个节点时(平均)需要进行多少次计算(迭代)才能到达任何节点。
这可以很容易地用数学来证明。
在我介绍它之前,让我澄清一些问题。在平衡二叉搜索树中查找的复杂度是O(log(n))。对于一般的二叉搜索树,它是O(n)。我将分别展示它们。
在平衡二叉搜索树中,在最坏情况下,我要查找的值在树的叶子节点上。基本上我会从根节点遍历到叶子节点,只查看树的每一层一次 -由于BST的排序结构。因此,我需要查找的次数就是树的层数。因此,问题归结为找到具有n个节点的树的层数的闭合形式表达式。
这就是我们将做一个简单归纳的地方。只有1层的树只有1个节点。2层的树有1+2个节点。3层1+2+4个节点等。模式很清楚:具有k层的树正好有
n=2^0+2^1+...+2^{k-1}
个节点。这是一个几何级数,意味着
n=2^k-1,
或者等价于:
k = log(n+1)
我们知道大O符号涉及到n的大值,因此常数是无关紧要的。因此复杂度为O(log(n))。
我将提供另一种 -更短- 的方式来展示相同的结果。由于在查找值时我们不断将树分成两半,需要这样做k次,其中k是层数,因此以下内容是正确的:
(n+1)/2^k = 1,
这意味着完全相同的结果。你必须说服自己,在n+1中的那个+1是从哪里来的,但即使你不注意它也没关系,因为我们谈论的是大的n值。
现在我们来讨论一般的二叉搜索树。在最坏情况下,它是完全不平衡的,意味着它的所有节点只有一个子节点(并且成为链接列表)。例如,请参见https://www.cs.auckland.ac.nz/~jmor159/PLDS210/niemann/s_fig33.gif
在这种情况下,要查找叶子中的值,我需要迭代所有节点,因此时间复杂度为O(n)。
最后注意的是,这些复杂度不仅适用于查找,还适用于插入和删除操作。
(当我达到10个声望点时,我会用更好看的LaTeX数学样式编辑我的方程式。现在SO不让我这样做。)
*
/ \
* *
/ \ / \
* * * *
/ \ / \ / \ / \
* * * * * * * *
n
/
n - 1
/
n - 2
/
...
1
1
的节点具有O(n)
时间复杂度。log(n)
成比例。在这种情况下,查找的时间复杂度为O(log(n))
,因为查找任何叶子节点都受到log(n)
次操作的限制。O(log(n))
的时间复杂度。