Algorithm 二叉树。识别T中的元素v,使T中的k-1元素小于v

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(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   B
     /     \
    Y      ...
     \     /
      Z   N
    
    A、 X、Y和Z都小于N(根据相同的规则,B也小于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