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

在Java中,如何将节点插入到完整的二叉树中?,java,data-structures,binary-tree,Java,Data Structures,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);

我们都知道,当插入到一个完整的二叉树中时,我们必须从左到右填充所有叶的所有子树。我使用以下方法将节点插入到完整的二叉树中

//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);
    }
}

因此,它将根更改为2。有没有办法将根更改回其原始值?我试图在不使用堆栈和队列的情况下实现这一点。

仅仅检查孩子们的孩子们来确定去哪一边是不够的,因为一旦树达到4号高度,这将不再有效,因为根之子的子从那个点开始不会改变,我们仍然可以向左或向右

我想到了两种方法:

  • 在每个节点上都有一个
    complete
    变量

    没有子节点的节点已完成

    具有两个大小相同的完整子节点的节点已完成

    每当更新树(插入或删除)时,也会为每个受影响的节点更新此变量

  • 根据大小从数学上确定子树是否完整

    大小为
    2^n-1
    的树已完成(对于某些
    n

    注意:只有当我们不允许在不保持树完整的情况下自由删除元素时,这才有效

  • 对于任何一种方法,在执行插入时,如果以下任一条件为真,我们将向左(
    left.add(item)
    ):

    • 左子树不完整
    • 左子树和右子树的大小相同(都是完整的,这意味着我们通过插入增加了高度)
    我将把实施细节留给你



    注意:在执行
    left时,您还需要更新大小。添加(项目)和<代码>右侧。添加(项目)。您可能只需在
    add
    函数中粘贴一个
    size++
    ,因为我们添加了1个元素,因此大小无论如何都会增加1。

    仅检查子元素的子元素以确定要转到哪一侧是不够的,因为一旦树达到高度4,这将不再起作用,因为根之子的子从那个点开始不会改变,我们仍然可以向左或向右

    我想到了两种方法:

  • 在每个节点上都有一个
    complete
    变量

    没有子节点的节点已完成

    具有两个大小相同的完整子节点的节点已完成

    每当更新树(插入或删除)时,也会为每个受影响的节点更新此变量

  • 根据大小从数学上确定子树是否完整

    大小为
    2^n-1
    的树已完成(对于某些
    n

    注意:只有当我们不允许在不保持树完整的情况下自由删除元素时,这才有效

  • 对于任何一种方法,在执行插入时,如果以下任一条件为真,我们将向左(
    left.add(item)
    ):

    • 左子树不完整
    • 左子树和右子树的大小相同(都是完整的,这意味着我们通过插入增加了高度)
    我将把实施细节留给你



    注意:在执行
    left时,您还需要更新大小。添加(项目)和<代码>右侧。添加(项目)。您可能只需在
    add
    函数中粘贴
    size++
    ,因为我们添加了1个元素,因此大小无论如何都会增加1。

    多亏了Dukeling的回答,实现该方法的正确方法是从数学上确定子树是否已满。代码如下:

    //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;
        }
    }
    
    //字段
    私人物品;
    私有整数大小;
    私人CBTree左、右;
    //添加方法
    公共作废新增(T项)
    {
    if(left==null)
    {
    左=新的CBTree(项目);
    }
    else if(right==null)
    {
    右=新的CBTree(项目);
    }
    else if(leftFull())
    {
    对。添加(项目);
    }
    其他的
    {
    左。添加(项目);
    }
    大小++;
    }
    //检查左子树是否已满
    公共布尔leftFull()
    {
    使用int,leafs=1;
    while(leafs=(leafs/2))
    {
    返回true;
    }
    其他的
    {
    返回false;
    }
    }
    
    多亏了杜克林的回答,实现该方法的正确方法是从数学上确定子树是否已满。代码如下:

    //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;
        }
    }
    
    //字段
    私人物品;
    私有整数大小;
    私人CBTree左、右;
    //添加方法
    公共作废新增(T项)
    {
    if(left==null)
    {
    左=新的CBTree(项目);
    }
    else if(right==null)
    {
    右=新的CBTree(项目);
    }
    else if(leftFull())
    {
    对。添加(项目);
    }
    其他的
    {
    左。添加(项目);
    }
    大小++;
    }
    //检查左子树是否已满
    公共布尔leftFull()
    {
    使用int,leafs=1;
    while(leafs=(leafs/2))
    {
    返回true;
    }
    其他的
    {
    返回false;
    }
    }
    
    是否可能重复@JimMischel我的问题与您链接的问题不同。他们的解决方案似乎和我的一样失败了。多亏了杜克林,我已经找到了实现该方法的正确方法。我将在一点后发布解决方案。可能重复吗@JimMischel我的问题与您链接的问题不同。他们的解决方案似乎和我的一样失败了。多亏了杜克林,我已经找到了实现该方法的正确方法。我将在稍后发布解决方案。更糟糕的是:SO用户回来说“没关系,我想出来了”而不接受答案,或者SO用户说你给了他们正确的答案,但他们自己做了回答?更糟糕的是:SO用户回来说“没关系,我想出来了”而不接受答案,或者让SO用户说你给了他们正确的答案,但作为回报,他们自己回答?如果其他用户帮助显示问题,那么你为什么不接受他的答案?如果其他用户