简体   繁体   English

有效地为父母搜索二叉搜索树

[英]searching a binary search tree for parents efficiently

I'm trying to solve the following problem:我正在尝试解决以下问题:

at first we have a bst with root 0 and nothing else.起初,我们有一个根为 0的 bst 仅此而已。 not we add n given numbers like a which:不是我们添加n 个给定的数字,例如:

not for instance we start to add n = 7 numbers to the tree:不是例如我们开始向树添加 n = 7 个数字:
19 3 5 25 21 -4 2 19 3 5 25 21 -4 2
after adding all the numbers,the goal is to find the parent of each node in the order they were added:添加所有数字后,目标是按照添加顺序找到每个节点的父节点:
0 19 3 19 25 0 3 0 19 3 19 25 0 3

My first approach was to build the tree while adding the nodes and print the parent at the same time:我的第一种方法是在添加节点的同时构建树并同时打印父节点:

    private static TreeNode treeInsert(TreeNode root, TreeNode newNode) {
    TreeNode y = null;
    TreeNode x = root;
    while (x != null) {
        y = x;
        if (newNode.key < x.key) x = x.left;
        else x = x.right;

    }
    newNode.parent = y;

    if (y == null) root = newNode;
    else if (newNode.key < y.key) y.left = newNode;
    else y.right = newNode;

    return newNode;

}

and this auxiliary class:还有这个辅助 class:

class TreeNode {
    TreeNode left;
    TreeNode right;
    TreeNode parent;
    int key;

   public TreeNode(int key) {
        this.key = key;

   }

so I can find the parent.The problem here is this algorithm is to slow.所以我可以找到父母。这里的问题是这个算法很慢。 if the given numbers are too many and if we consider the tree is unbalanced then it might take forever to add new nodes.如果给定的数字太多并且我们认为树是不平衡的,那么添加新节点可能需要很长时间。 The time limit on this problem is 1 and because of the reasons I mentioned I'm exceeding that limit.这个问题的时间限制是1 ,由于我提到的原因,我超过了这个限制。 I cant balance the tree because the the parents change.我无法平衡树,因为父母变了。 But maybe there is a way to solve the problem without constructing a bst and just focusing on finding the parents using the numbers.但也许有一种方法可以解决问题,而无需构建 bst,而只需专注于使用数字找到父母。

Thank you.谢谢你。

We can represent existing binary search tree by segment.我们可以逐段表示现有的二叉搜索树。

Let say, we already added:比方说,我们已经添加了:

0, 21, 10, -4

So, basically, we have those segment [-4 0][0 10][10 21]所以,基本上,我们有那些段[-4 0][0 10][10 21]

When we add a new number x , we just need to find what is the segment that this number if falling to.当我们添加一个新的数字x时,我们只需要找到这个数字如果下降到的段是什么。 Let say x = 3假设x = 3

So, the segment is [0 10] => we break this into [0 3][3 10]所以,段是[0 10] => 我们把它分成[0 3][3 10]

What next is to determine what is the parent of this node.接下来是确定这个节点的父节点是什么。 Simple, just need to keep track of what node is being added later in the segment.很简单,只需要跟踪稍后在段中添加的节点。 In this case, 10 definitely added after 0, so 10 should be the parent.在这种情况下,肯定会在 0 之后添加 10,因此 10 应该是父级。

Let's say比方说

class Segment{
    int start, end, later;
}

So, for the above sequence, we have the list of segment:因此,对于上述序列,我们有段列表:

Segment (-4, 0, -4), Segment(0, 10, 10) , Segment (10, 21, 10)

In case x = 11, which falls into Segment (10, 21, 10) so parent node will also be 10 .如果 x = 11,它属于Segment (10, 21, 10) ,那么父节点也将是10

After adding 11 , we will have the list of segment:添加11后,我们将获得段列表:

Segment (-4, 0, -4), Segment(0, 10, 10), Segment (10, 11 , 11) , Segment (11, 21, 11)

In case that the number is not inside any segment, this case should also be simple.如果数字不在任何段内,这种情况也应该很简单。 I will left this case for reader to figure it out.我将把这个案例留给读者来解决。

Maintaining a balanced BST to store list of segment, and we could obtain O(n log n) solution.维护一个平衡的 BST 来存储段列表,我们可以获得 O(n log n) 的解决方案。

You are correct that building the tree can be slow.你是对的,构建树可能很慢。 If the tree becomes degenerate (ie it has long deep chains), then building the tree will take O ( n ²).如果树变得退化(即它有很长的深链),那么构建树将花费O ( n ²)。 Here is an O ( n log n ) approach.这是一个O ( n log n ) 方法。

Consider the tree after inserting 19 and 3:考虑插入 19 和 3 后的树:

0
 \
  \
   19
  /
 3

We can predict the parent of the following value to be inserted, x :我们可以预测要插入的以下值的父级x

  • if x < 0 then its parent will be 0;如果x < 0 则其父级将为 0;
  • if 0 < x < 3 then its parent will be 3 (left-hand child, but that is not important);如果 0 < x < 3 那么它的父级将是 3(左手孩子,但这并不重要);
  • if 3 < x < 19 then its parent will be 3 (right-hand child);如果 3 < x < 19 那么它的父级将是 3(右手孩子);
  • if 19 < x then its parent will be 19.如果 19 < x那么它的父级将是 19。

Let's write this visually as让我们直观地写成

values         0       3                     19
parents   (0)     (3)             (3)             (19)

When we insert 5, we look it up, print its parent (that is 3) and update our data:当我们插入 5 时,我们查找它,打印它的父项(即 3)并更新我们的数据:

values         0       3          5          19
parents   (0)     (3)       (5)        (5)        (19)

What changed?发生了什么变化?

  • we inserted 5 in its sorted place (between 3 and 19);我们在其排序位置插入了 5(在 3 到 19 之间);
  • we changed 3 to 5 in the corresponding parents position;我们在相应的父母 position 中将 3 更改为 5;
  • we inserted another 5 next to the first one.我们在第一个旁边插入了另外 5 个。

You can think of the top line as keys and the bottom line as values/payload.您可以将顶线视为键,将底线视为值/有效负载。 So basically you need a structure that allows O (log n ) insertions and look ups.所以基本上你需要一个允许O (log n ) 插入和查找的结构。 I personally like skip lists for the job, but any form ofbalanced trees will also work.我个人喜欢这项工作的跳过列表,但任何形式的平衡树也可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM