Java 如何返回双链接列表并删除树的叶子?

Java 如何返回双链接列表并删除树的叶子?,java,algorithm,list,recursion,Java,Algorithm,List,Recursion,我在做一个类似SPOJ的任务。目标是在二叉树(不一定是BST)中找到叶子,从树中删除它们,并将它们作为一种双链表返回,使用相同的结构-树节点,不需要额外导入。例如,如果节点2、4和3从树中删除,函数将返回列表的第一个非空元素:null null。TreeNode有一个值和左右指针 我使用了递归并取消了叶子,将它们从树中删除,然后在列表中重新创建它们。为了保持向列表末尾添加元素的效率,我将指针指向列表的最后一个元素。这就产生了一个众所周知的问题,即改变传递给函数的对象。这是我的密码: public

我在做一个类似SPOJ的任务。目标是在二叉树(不一定是BST)中找到叶子,从树中删除它们,并将它们作为一种双链表返回,使用相同的结构-树节点,不需要额外导入。例如,如果节点2、4和3从树中删除,函数将返回列表的第一个非空元素:null null。TreeNode有一个值和左右指针

我使用了递归并取消了叶子,将它们从树中删除,然后在列表中重新创建它们。为了保持向列表末尾添加元素的效率,我将指针指向列表的最后一个元素。这就产生了一个众所周知的问题,即改变传递给函数的对象。这是我的密码:

public TreeNode getLeaves(TreeNode root)
{
    if(root == null)
        return null;

    TreeNode start = new TreeNode(Integer.MIN_VALUE);
    TreeNode[] end = {start};
    getLeaves(root, start, end);
    return start;
}

private void getLeaves(TreeNode root, TreeNode start, TreeNode[] end)
{
    if(root == null)
        return;

    if(root.left == null && root.right == null)
    {
        addToList(root, start, end);
        root = null;
        return;
    }
    getLeaves(root.left, start, end);
    getLeaves(root.right, start, end);
}

private void addToList(TreeNode element, TreeNode start, TreeNode[] end)
{
    if(end[0].value != Integer.MIN_VALUE)
    {
        TreeNode t = new TreeNode (element.value);
        end[0].right = t;
        t.left = end[0];
        end[0] = t;
    }
    else
    {
        start.value = element.value;
    }
}

从树中删除叶子不起作用,但列表会正确返回。但是,将“start”TreeNode的值设置为最小int值而不是使用null引用会让我感到不舒服,使用数组也是如此。使用原子引用会使它更加混乱。我很确定有一种方法可以以更优雅的方式完成(并正确地删除叶子),可能是通过改变分配开始树节点和结束树节点的方法。我觉得我的方法和/或对其工作方式的理解有问题。你能帮我把它转换成一段简洁的代码并解释一下我的缺点吗?

你的第二个
GetLeaves
函数有一个错误。语句
root=null
将局部变量
root
的值设置为null,但其父变量将保留对叶的引用

如果将方法
bool isLeaf()
添加到
TreeNode
,您将有一个更轻松的时间。我把你的代码修改成了我认为可能有用的东西

private bool isLeaf()
{
    // This method should be in TreeNode
    return left == null && right == null;
}
// Also, TreeNode should have an Add(TreeNode) method

public TreeNode getLeaves(TreeNode root)
{
    if( root == null )  // check if the whole tree is empty
        return null;  // return something relevant here
    else if( root.isLeaf() )
        return root;  //cannot remove this leaf, unfortunately
    TreeNode leaves = new TreeNode()
    getLeaves(root, leaves);
    return leaves;
}
private void getLeaves(TreeNode current, TreeNode leaves)
{
    // current is guaranteed to be non-null and not a leaf itself.
    if( current.left.isLeaf() ) {
        leaves.add(current.left);
        current.left = null;
    } else {
        getLeaves(current.left, leaves);
    }
    if( current.right.isLeaf() ) {
        leaves.add(current.right);
        current.right = null;
    } else {
        getLeaves(current.right, leaves);
    }
}

大卫,你是100%正确的。谢谢你的帮助。如果有人想知道,这是我迄今为止提出的最优雅的解决方案,包括David的改进。我唯一不确定的是addToList方法是否应该是静态的,或者在元素的上下文中调用它更合适/更通用

public TreeNode getLeaves(TreeNode root)
{
    if(root == null)
        return null;

    if(root.isLeaf())
        return root;

    TreeNode[] listEdges = {null, null};
    getLeaves(root, listEdges);
    return listEdges[0];
}

private void getLeaves(TreeNode root, TreeNode[] edges)
{
    if(root == null)
        return;

    if(root.left != null && root.left.isLeaf())
    {
        addToList(edges, root.left);
        root.left = null;
    }

    if(root.right != null && root.right.isLeaf())
    {
        addToList(edges, root.right);
        root.right = null;
    }
    getLeaves(root.left, edges);
    getLeaves(root.right, edges);
}

private static void addToList(TreeNode[] edges, TreeNode element)
{
    if(edges[1] != null)
    {
        edges[1].right = element;
        element.left = edges[1];
        edges[1] = element;
    }
    else
    {
        edges[0] = element;
        edges[1] = edges[0];
    }
}

public boolean isLeaf()
{
    return this.right == null && this.left == null;
}