Algorithm 二叉树。识别T中的元素v,使T中的k-1元素小于v
我有个问题需要解决。我不是在寻找答案,而是想知道我该去哪里。我有一个算法,但它不是O(logn) 给定二叉树T和一个不大于T中节点数的正整数k,编写伪代码来标识T中的元素v,从而精确地确定k− 1 T中的元素小于v。您的代码所花费的时间最多应与 T的高度 我在这里的基本想法是,首先检查左树,检查左树的大小。如果左树的大小大于k-1,则我将继续左搜索。否则我会马上搜索。如果整个左树不包含包含k-1元素的节点,那么我搜索右子树。问题是,我知道这不是O(logn),因为在最坏的情况下,我必须搜索树中的每个节点 我有什么遗漏吗?任何提示或帮助都会很棒,但请不要只是给我一个答案。(我假设这棵树实际上是一棵二叉搜索树,而不仅仅是任何旧的二叉树) 您的算法是Algorithm 二叉树。识别T中的元素v,使T中的k-1元素小于v,algorithm,binary-tree,binary-search-tree,Algorithm,Binary Tree,Binary Search Tree,我有个问题需要解决。我不是在寻找答案,而是想知道我该去哪里。我有一个算法,但它不是O(logn) 给定二叉树T和一个不大于T中节点数的正整数k,编写伪代码来标识T中的元素v,从而精确地确定k− 1 T中的元素小于v。您的代码所花费的时间最多应与 T的高度 我在这里的基本想法是,首先检查左树,检查左树的大小。如果左树的大小大于k-1,则我将继续左搜索。否则我会马上搜索。如果整个左树不包含包含k-1元素的节点,那么我搜索右子树。问题是,我知道这不是O(logn),因为在最坏的情况下,我必须搜索树中的
O(d)
,其中d
是树的最大深度
这是因为每次进行比较时,您都会继续往下走一层(假设您还没有找到元素)。因此,您最多只能进行树中级别的比较
所以,除非你的树真的是不平衡的,否则你实际上永远不会浏览每一个元素。事实上,如果你可以假设这棵树是平衡的,那么你已经可以走了(为什么?)如果我们谈论的是一棵普通的二叉树,那么很容易证明你需要探索整棵树才能找到这样一个节点,所以我假设我们谈论的是一棵二叉搜索树 在二元搜索树中,以下值小于节点N:
- 节点A、其左子节点及其所有子节点,其中节点B是节点A的右子节点,节点B是节点N或其任何祖先节点
A、 X、Y和Z都小于N(根据相同的规则,B也小于N)A / \ X B / \ Y ... \ / Z N
- 节点N的左子节点
m
元素较小的节点
x
=左子树中的节点数(如果没有左子树,则x=0)x=m
,则返回当前节点x
,则向左递归x>m
,则设置m=m-x-1
并向右递归由于您只能向左或向右移动,并且节点计数是恒定的(因为它是在节点级别上给出的),因此运行时间是
O(h)
,其中h
是树的高度,在平衡树中是O(log n)
。它的算法几乎与quickselect相同。根据左分支的大小,递归到左分支或右分支
Find(T, k) :=
size(T.left) == k - 1 -> return T
size(T.left) > k - 1 -> return Find(T.left, k)
size(T.left) < k - 1 -> return Find(T.right, k - size(T.left) - 1)
仔细查看您拥有的树结构,以及它附带的保证。你知道一棵子树有多大而不经过它吗?左子树中的所有内容是否都小于或等于当前节点上的值?这些价值观是不同的吗?你知道一些关于子树的高度而不去探索它们吗?“T的高度”实际上与“logn”成正比吗?我应该提到,每个节点都包含一个元素大小,它是在该节点上扎根的节点数。所以我可以通过查看它的size元素来知道子树有多大。左树中的所有内容都将小于当前节点的值。大小值并不总是不同的。可以有多个大小为k-1的节点。根据我在课堂上学到的知识,树的高度始终与logn成正比。当您在节点v处向右移动时,需要将搜索值调整为
k-(1+v的左子树大小)
。除此之外,您还可以按O(树高)进行下降,因为您可以使用该大小计数器在每个节点上做出正确的决定。您能详细说明一下吗?我还是不明白。我仍然觉得它需要返回树,检查左树大小为k-1的元素的右子树。假设我沿着左子树一直工作,检查每个左子树,直到到达一个空链接。我是否应该检查左子树为k-1的元素的右子树?看起来与问题中描述的相似,但问题的答案是,确实是O(n),而不是O(d)。
Find(T, k) :=
while size(T.left) != k - 1:
if size(T.left) > k - 1:
T = T.left
else:
T = T.right
k -= size(T.left) + 1
return T