简体   繁体   English

如何在Java中将节点插入完整的二叉树中?

[英]How to insert a node into a complete binary tree in Java?

As we all know, when inserting into a complete binary tree we have to fill all the children for all the leafs from left to right. 众所周知,当插入完整的二叉树时,我们必须从左到右填充所有叶子的所有子代。 I have the following method that inserts a node into a complete binary tree. 我有以下将节点插入完整的二叉树的方法。

//fields
private T item;
private int size;
private CBTree<T> left, right;

//add method
public void add(T item) 
{
    if(left == null)
    {
        left = new CBTree<T>(item);
        size += left.size;
    }
    else if(right == null)
    {
        right = new CBTree<T>(item);
        size += right.size;
    }
    else if(!((left.left != null) && (left.right != null)) && 
           ((right.left == null) || (right.right == null)))
    {
        left.add(item);
    }
    else
    {
        right.add(item);
    }
}

The problem with this implementation is that after the 11th node it adds the 12th node to the left child of 8 instead of 6. I understand that this is happening because the following line is reassigning the root of this tree to be the left child of the root. 此实现的问题在于,在第11个节点之后,它将第12个节点添加到8的左子节点,而不是6。我知道这是在发生,因为以下行将此树的根重新分配为该树的根节点根。

left.add(item);

So it is changing the root to 2. Is there a way to change the root back to its original value? 因此,它会将根更改为2。是否有办法将根更改回其原始值? I am trying to accomplish this without using stacks and queues. 我正在尝试不使用堆栈和队列来完成此操作。

It's not sufficient to just check children of children to determine which side to go to, because as soon as the tree reaches height 4 that won't work any more, since children of children of the root won't change from that point forward yet we can still go either left or right. 仅检查孩子们的孩子以确定去哪一边是不够的,因为一旦树达到高度4,就不再起作用了,因为有根孩子的孩子从那以后不会改变我们仍然可以向左或向右走。

2 approaches come to mind: 我想到2种方法:

  1. Have a complete variable at each node. 在每个节点上都有一个complete变量。

    A node with no children is complete. 没有子节点的节点已完成。

    A node with 2 complete children of equal size is complete. 一个具有2个相等大小的完整子代的节点是完整的。

    Whenever update the tree (insert or delete) you update this variable for each affected node as well. 每当更新树(插入或删除)时,您也会为每个受影响的节点更新此变量。

  2. Mathematically determine whether a subtree is complete based on the size. 根据大小数学确定子树是否完整。

    A tree of size 2^n - 1 is complete (for some n ). 一棵大小为2^n - 1树是完整的(对于某些n )。

    Note: this will only work if we're not allowed to freely delete elements without keeping the tree complete. 注意:这仅在不允许我们在不使树完整的情况下自由删除元素时起作用。

For either approach, when doing an insertion, we go left ( left.add(item) ) if either of these conditions are true: 对于这两种方法,在执行插入操作时,如果以下任一条件为真,我们将向左( left.add(item)left.add(item)

  • the left subtree is not complete 左子树不完整
  • the left and right subtrees are of the same size (both complete, meaning we're increasing the height with this insertion) 左和右子树的大小相同(都完整,这意味着我们通过插入来增加高度)

I'll leave the implementation details to you. 我将把实施细节留给您。


Note: you need to also update size when doing left.add(item); 注意:做left.add(item);需要更新大小left.add(item); and right.add(item); right.add(item); . You could probably just stick a size++ in the add function, since we're adding 1 element so size increases by 1 no matter what. 您可能只是将size++粘贴在add函数中,因为我们要添加1个元素,所以无论如何大小都会增加1。

Thanks to Dukeling's answer, the correct way to implement the method was to mathematically determine if the subtree was full. 感谢Dukeling的回答,实现该方法的正确方法是数学确定子树是否已满。 Here is the code: 这是代码:

//fields
private T item;
private int size;
private CBTree<T> left, right;

//add method
public void add(T item) 
{
    if(left == null)
    {
        left = new CBTree<T>(item);
    }
    else if(right == null)
    {
        right = new CBTree<T>(item);
    }
    else if(leftFull())
    {
        right.add(item);
    }
    else
    {
        left.add(item);
    }
    size++;
}

//Checks if the left subtree is full
public boolean leftFull()
{
    int used, leafs = 1;
    while(leafs <= size + 1)
    {
        leafs *= 2;
    }

    leafs /= 2;
    used = (size + 1) % leafs;
    if(used >= (leafs / 2))
    {
        return true;
    }
    else
    {
        return false;
    }
}

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

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