我有兴趣查找BST给定范围内的所有整数。 我想知道如果BST是用节点创建的,那我将如何去做,因此我必须使用单链表。 返回的链表中项目的顺序无关紧要。

例如,考虑以下所示的树,

在此处输入图片说明

范围是[6,13],则列表应包括6-> 7-> 8-> 10-> 13或13-> 10-> 8-> 7-> 6。 就像我说的,返回列表中的顺序无关紧要。

而且,运行时约束为O(n),其中n是树中的节点数。

提前致谢!

===============>>#1 票数:1 已采纳

您可以仅使用2个堆栈来完成此操作...

让我们从2个堆栈开始,1个是简单的待办事项堆栈(例如,包含您应访问的节点),另一个是包含结果的堆栈。

从根节点开始,如果节点在范围内,则将其推入结果堆栈,然后将两个子节点推入待办事项堆栈。 如果超出范围,可能会发生2种情况:1.)小于我们范围内的最小值->将其推入待办事项堆栈中是正确的子项。2.)大于我们范围内的最大值->脓是待办事项中的左子项堆

好的,让我们将其创建为一些有用的算法:

List<BSTNode*> FindAllInRange(BSTNode* root, int low, int high)
{
    Stack<BSTNode*> todo;              //< Todo stack
    Stack<BSTNode*> results;           //< Results stack

    // Start with root node
    todo.push(root);

    // While we have nodes to process
    while(todo.size() > 0)
    {
        // Get top node, and pop it from stack
        BSTNode* curr = todo.top();
        todo.pop();

        // If its value is less than the lowest value in range
        if(curr->value < low)
        {
            // Push right children if exists (as it may be higher than lowest value in range)
            if(node->right)
                todo.push(node->right);
        }
        // If its value is greater than the highest value in range
        else if(curr->value > high)
        {
            // Push left children if exists (as it may be lower than highest value in range)
            if(node->left)
                todo.push(node->left);
        }
        // Otherwise (we're in range)
        else
        {
            // Push current node to results stack
            results.push(curr);

            // If right node exists, push it on todo stack
            if(node->right)
                todo.push(node->right);

            // If left node exists, push it on todo stack
            if(node->left)
                todo.push(node->left);
        }
    }

    // Now you just have to convert the stack to list (and possibly sort it, reverse sort it, ...)
    return results.ConvertToList();
}

请注意,这只是类似C ++语言的伪代码。

===============>>#2 票数:1

如果您具有BST的基本知识,则应该熟悉从树中检索一组排序的元素实际上是非常简单的。 如果您熟悉LVR / RVL遍历,则可以跳到“答案”。

循环遍历树:

遍历树通常被描述为三个字母LVR的组合。 L左。 R是正确的。 V表示访问。

这描述了遍历树时要遵循的模式。 L表示您将树升至左节点(如果存在)。 R代表正确。 V表示当前节点上的某些操作,例如print。 它使用重复!。 这很重要。

现在。 如何获得排序集。 当访问意味着打印或推送时,它是简单的LVR

示例-完整的演练:

 (8) You start in root. `L` - go left. 
  (3) You are in (3). You go `LVR` for this node again - recurrence. `L`
    (1) You are in (1). Now *again* `LVR`.
    However there is no left node so we go to `V` - visit/print 1. Now `R` - no right node. End. By recurrence we go back to 3.
  (3) - We're done with `L`. We do `V`. Print 3.
  (3) - `R`.
    (6) You are in (6) - `LVR` again. 'L'
      (4) You are in (4) - `L` does not exists. Print 4. `R` does not exist. Back one level.
    (6) - `V`. Print 6.
    (6) - `R`.
      You are in (7) - `L` does not exists. Print 7. `R` does not exist. Back one level.
    (6) - `LVR` Done. Back one level.
  (3) - `LVR` Done. Back one level.
(8) - `R`.
  (10) You are in 10. `L` Does not exist.
  (10) `V`. Print 10.
  (10) `R`.
    (14) You are in 14.
    (14) `L`.
      (13) You are in 13. `L` does not exists. Print 14. `R` does not exist. Back one level.
    (14) `V`. Print 14.
    (14) `R`. Does not exist. Back one level.
  (10) Done with `R`. Back one level.
(8) Done with `R`. Back one level.
Haha we were on root node so we are done.

如果您将遵循打印。 事实证明,您按照从低到高的顺序打印了整套打印机。 RVL模式将执行类似的操作,但是由于您从第1个位置向右走,因此您将首先访问最右边的节点,因此顺序将降序。 由于没有魔法,您只需要访问每个节点一次,因此时间复杂度为O(n)

答案:

简单的方法。 进行正常的LVR遍历。 但是仅在适合范围时才打印数字。 几乎没有困难,但更好的平均和极端情况。 找到起始节点。 然后开始遍历,并在每次访问时仅将其与上限进行比较,并在节点数据超过上限时停止。

当然,除了打印之外,您还可以使用堆栈或其他要按排序顺序存储元素的内容(例如列表)。

  ask by Nima Vaziri translate from so

未解决问题?本站智能推荐: